mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
2008-04-04 Emmanuele Bassi <ebassi@openedhand.com>
Bug #864 - Allow instantiating and subclassing of ClutterStage * clutter/Makefile.am: Add clutter-stage-window.[ch] * clutter/clutter-stage-manager.c: (_clutter_stage_manager_remove_stage): Do not warn if removing a stage we don't manage, as we might be invoked multiple times during a ClutterState dispose sequence. * clutter/clutter-actor.c: * clutter/clutter-backend.[ch]: * clutter/clutter-main.c: * clutter/clutter-private.h: * clutter/clutter-stage.[ch]: Make ClutterStage a proxy actor, with a private actor implementing the ClutterStageWindow interface for handling the per-backend realization, painting and unrealization, plus all the windowing system abstraction. * clutter/x11/clutter-event-x11.c: * clutter/x11/clutter-stage-x11.[ch]: Port the X11 backend to the new backend and stage API and semantics. * clutter/glx/clutter-backend-glx.c: * clutter/glx/clutter-stage-glx.c: Port the GLX backend to the new backend and stage API and semantics. * clutter/eglx/clutter-backend-egl.[ch]: * clutter/eglx/clutter-stage-egl.[ch]: Port the EGLX backend to the new backend and stage API and semantics (untested). * tests/test-multistage.c (on_button_press): Rename clutter_stage_create_new() to clutter_stage_new().
This commit is contained in:
parent
beb03b9750
commit
f859135082
35
ChangeLog
35
ChangeLog
@ -1,3 +1,38 @@
|
||||
2008-04-04 Emmanuele Bassi <ebassi@openedhand.com>
|
||||
|
||||
Bug #864 - Allow instantiating and subclassing of ClutterStage
|
||||
|
||||
* clutter/Makefile.am: Add clutter-stage-window.[ch]
|
||||
|
||||
* clutter/clutter-stage-manager.c:
|
||||
(_clutter_stage_manager_remove_stage): Do not warn if removing
|
||||
a stage we don't manage, as we might be invoked multiple times
|
||||
during a ClutterState dispose sequence.
|
||||
|
||||
* clutter/clutter-actor.c:
|
||||
* clutter/clutter-backend.[ch]:
|
||||
* clutter/clutter-main.c:
|
||||
* clutter/clutter-private.h:
|
||||
* clutter/clutter-stage.[ch]: Make ClutterStage a proxy actor,
|
||||
with a private actor implementing the ClutterStageWindow
|
||||
interface for handling the per-backend realization, painting
|
||||
and unrealization, plus all the windowing system abstraction.
|
||||
|
||||
* clutter/x11/clutter-event-x11.c:
|
||||
* clutter/x11/clutter-stage-x11.[ch]: Port the X11 backend
|
||||
to the new backend and stage API and semantics.
|
||||
|
||||
* clutter/glx/clutter-backend-glx.c:
|
||||
* clutter/glx/clutter-stage-glx.c: Port the GLX backend to
|
||||
the new backend and stage API and semantics.
|
||||
|
||||
* clutter/eglx/clutter-backend-egl.[ch]:
|
||||
* clutter/eglx/clutter-stage-egl.[ch]: Port the EGLX backend
|
||||
to the new backend and stage API and semantics (untested).
|
||||
|
||||
* tests/test-multistage.c (on_button_press): Rename
|
||||
clutter_stage_create_new() to clutter_stage_new().
|
||||
|
||||
2008-04-04 Neil Roberts <neil@o-hand.com>
|
||||
|
||||
Applied patch from bug #810.
|
||||
|
@ -162,6 +162,7 @@ source_c = \
|
||||
clutter-shader.c \
|
||||
clutter-stage.c \
|
||||
clutter-stage-manager.c \
|
||||
clutter-stage-window.c \
|
||||
clutter-texture.c \
|
||||
clutter-timeline.c \
|
||||
clutter-timeout-pool.c \
|
||||
@ -175,6 +176,7 @@ source_h_priv = \
|
||||
clutter-private.h \
|
||||
clutter-id-pool.h \
|
||||
clutter-script-private.h \
|
||||
clutter-stage-window.h \
|
||||
$(NULL)
|
||||
|
||||
libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_API_VERSION@_la_LIBADD = \
|
||||
|
@ -2447,7 +2447,7 @@ clutter_actor_queue_redraw (ClutterActor *self)
|
||||
|
||||
/* FIXME: should we check we're visible here? */
|
||||
if ((stage = clutter_actor_get_stage (self)) != NULL)
|
||||
clutter_stage_queue_redraw (CLUTTER_STAGE(stage));
|
||||
clutter_stage_queue_redraw (CLUTTER_STAGE (stage));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "clutter-fixed.h"
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-debug.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT);
|
||||
|
||||
@ -138,8 +139,9 @@ _clutter_backend_post_parse (ClutterBackend *backend,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ClutterActor*
|
||||
ClutterActor *
|
||||
_clutter_backend_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
@ -147,6 +149,7 @@ _clutter_backend_create_stage (ClutterBackend *backend,
|
||||
ClutterActor *stage = NULL;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (wrapper), FALSE);
|
||||
|
||||
context = clutter_context_get_default ();
|
||||
|
||||
@ -155,28 +158,30 @@ _clutter_backend_create_stage (ClutterBackend *backend,
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (klass->create_stage)
|
||||
stage = klass->create_stage (backend, error);
|
||||
stage = klass->create_stage (backend, wrapper, error);
|
||||
|
||||
if (!stage)
|
||||
return NULL;
|
||||
|
||||
_clutter_stage_manager_add_stage (context->stage_manager,
|
||||
CLUTTER_STAGE(stage));
|
||||
_clutter_stage_manager_add_stage (context->stage_manager, wrapper);
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_redraw (ClutterBackend *backend, ClutterStage *stage)
|
||||
_clutter_backend_redraw (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (G_LIKELY(klass->redraw))
|
||||
if (G_LIKELY (klass->redraw))
|
||||
klass->redraw (backend, stage);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_ensure_context (ClutterBackend *backend, ClutterStage *stage)
|
||||
_clutter_backend_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
static ClutterStage *current_context_stage = NULL;
|
||||
@ -184,13 +189,16 @@ _clutter_backend_ensure_context (ClutterBackend *backend, ClutterStage *stage)
|
||||
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
if (stage != current_context_stage || !CLUTTER_ACTOR_IS_REALIZED(stage))
|
||||
if (stage != current_context_stage || !CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED(stage))
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
CLUTTER_NOTE (MULTISTAGE, "Stage is not realized");
|
||||
stage = NULL;
|
||||
}
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (G_LIKELY(klass->ensure_context))
|
||||
if (G_LIKELY (klass->ensure_context))
|
||||
klass->ensure_context (backend, stage);
|
||||
|
||||
/* FIXME: With a NULL stage and thus no active context it may make more
|
||||
|
@ -47,13 +47,14 @@ typedef struct _ClutterBackendClass ClutterBackendClass;
|
||||
|
||||
struct _ClutterBackend
|
||||
{
|
||||
/*< private >*/
|
||||
GObject parent_instance;
|
||||
ClutterBackendPrivate *priv;
|
||||
|
||||
};
|
||||
|
||||
struct _ClutterBackendClass
|
||||
{
|
||||
/*< private >*/
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* vfuncs */
|
||||
@ -61,7 +62,8 @@ struct _ClutterBackendClass
|
||||
GError **error);
|
||||
gboolean (* post_parse) (ClutterBackend *backend,
|
||||
GError **error);
|
||||
ClutterActor *(* create_stage) (ClutterBackend *backend,
|
||||
ClutterActor * (* create_stage) (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error);
|
||||
void (* init_events) (ClutterBackend *backend);
|
||||
void (* init_features) (ClutterBackend *backend);
|
||||
|
@ -104,6 +104,28 @@ clutter_get_show_fps (void)
|
||||
return clutter_show_fps;
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_maybe_setup_viewport (ClutterStage *stage)
|
||||
{
|
||||
if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES)
|
||||
{
|
||||
ClutterPerspective perspective;
|
||||
guint width, height;
|
||||
|
||||
clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height);
|
||||
clutter_stage_get_perspectivex (stage, &perspective);
|
||||
|
||||
CLUTTER_NOTE (PAINT, "Setting up the viewport");
|
||||
|
||||
cogl_setup_viewport (width, height,
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
perspective.z_far);
|
||||
|
||||
CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_redraw:
|
||||
@ -122,35 +144,21 @@ clutter_redraw (ClutterStage *stage)
|
||||
|
||||
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_NOTE (MULTISTAGE, "Redraw called for stage:%p", stage);
|
||||
|
||||
_clutter_backend_ensure_context (ctx->backend, stage);
|
||||
|
||||
/* Setup FPS count - not currently across *all* stages rather than per */
|
||||
if (clutter_get_show_fps ())
|
||||
if (G_UNLIKELY (clutter_get_show_fps ()))
|
||||
{
|
||||
if (!timer)
|
||||
timer = g_timer_new ();
|
||||
}
|
||||
|
||||
/* The below cant go in stage paint as base actor_paint will get
|
||||
* called before the below (and break picking etc)
|
||||
/* The code below can't go in stage paint as base actor_paint
|
||||
* will get called before it (and break picking, etc)
|
||||
*/
|
||||
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);
|
||||
}
|
||||
clutter_maybe_setup_viewport (stage);
|
||||
|
||||
/* Call through to the actual backend to do the painting down from
|
||||
* the stage. It will likely need to swap buffers, vblank sync etc
|
||||
@ -159,7 +167,7 @@ clutter_redraw (ClutterStage *stage)
|
||||
_clutter_backend_redraw (ctx->backend, stage);
|
||||
|
||||
/* Complete FPS info */
|
||||
if (clutter_get_show_fps ())
|
||||
if (G_UNLIKELY (clutter_get_show_fps ()))
|
||||
{
|
||||
timer_n_frames++;
|
||||
|
||||
@ -234,24 +242,8 @@ _clutter_do_pick (ClutterStage *stage,
|
||||
|
||||
_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);
|
||||
}
|
||||
/* needed for when a context switch happens */
|
||||
clutter_maybe_setup_viewport (stage);
|
||||
|
||||
cogl_paint_init (&white);
|
||||
cogl_enable (0);
|
||||
@ -276,7 +268,7 @@ _clutter_do_pick (ClutterStage *stage,
|
||||
/* glEnable (GL_DITHER); we never enabled this originally, so its
|
||||
probably not safe to then enable it */
|
||||
|
||||
glReadPixels(x, viewport[3] - y -1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
|
||||
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);
|
||||
@ -988,7 +980,6 @@ clutter_init_with_args (int *argc,
|
||||
GOptionContext *context;
|
||||
GOptionGroup *group;
|
||||
gboolean res;
|
||||
GError *stage_error;
|
||||
ClutterActor *stage;
|
||||
|
||||
if (clutter_is_initialized)
|
||||
@ -1018,13 +1009,13 @@ clutter_init_with_args (int *argc,
|
||||
|
||||
clutter_context = clutter_context_get_default ();
|
||||
|
||||
stage_error = NULL;
|
||||
stage = _clutter_backend_create_stage (clutter_context->backend,
|
||||
&stage_error);
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
if (!stage)
|
||||
{
|
||||
g_propagate_error (error, stage_error);
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_INTERNAL,
|
||||
"Unable to create the default stage");
|
||||
|
||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
@ -1032,8 +1023,7 @@ clutter_init_with_args (int *argc,
|
||||
|
||||
_clutter_feature_init ();
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE(clutter_stage_get_default()),
|
||||
g_get_prgname ());
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), g_get_prgname ());
|
||||
|
||||
return CLUTTER_INIT_SUCCESS;
|
||||
}
|
||||
@ -1089,7 +1079,6 @@ clutter_init (int *argc,
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
ClutterActor *stage;
|
||||
GError *stage_error;
|
||||
|
||||
if (clutter_is_initialized)
|
||||
return CLUTTER_INIT_SUCCESS;
|
||||
@ -1115,15 +1104,10 @@ clutter_init (int *argc,
|
||||
context = clutter_context_get_default ();
|
||||
|
||||
/* Stage will give us a GL Context etc */
|
||||
stage_error = NULL;
|
||||
|
||||
stage = _clutter_backend_create_stage (context->backend, &stage_error);
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
if (!stage)
|
||||
{
|
||||
CLUTTER_NOTE (MISC, "stage failed to initialise.");
|
||||
g_critical (stage_error->message);
|
||||
g_error_free (stage_error);
|
||||
g_critical ("Unable to create the default stage");
|
||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
@ -1133,8 +1117,7 @@ clutter_init (int *argc,
|
||||
/* finally features - will call to backend and cogl */
|
||||
_clutter_feature_init ();
|
||||
|
||||
clutter_stage_set_title (CLUTTER_STAGE(clutter_stage_get_default()),
|
||||
g_get_prgname());
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), g_get_prgname ());
|
||||
|
||||
return CLUTTER_INIT_SUCCESS;
|
||||
}
|
||||
|
@ -40,12 +40,13 @@
|
||||
|
||||
#include <pango/pangoft2.h>
|
||||
|
||||
#include "clutter-stage-manager.h"
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-stage.h"
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-feature.h"
|
||||
#include "clutter-id-pool.h"
|
||||
#include "clutter-stage-manager.h"
|
||||
#include "clutter-stage-window.h"
|
||||
#include "clutter-stage.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -55,10 +56,11 @@ typedef enum {
|
||||
CLUTTER_ACTOR_IN_DESTRUCTION = 1 << 0,
|
||||
CLUTTER_ACTOR_IS_TOPLEVEL = 1 << 1,
|
||||
CLUTTER_ACTOR_IN_REPARENT = 1 << 2,
|
||||
CLUTTER_ACTOR_SYNC_MATRICES = 1 << 3 /* Used by stage to indicate GL
|
||||
CLUTTER_ACTOR_SYNC_MATRICES = 1 << 3, /* Used by stage to indicate GL
|
||||
* viewport / perspective etc
|
||||
* needs (re)setting.
|
||||
*/
|
||||
CLUTTER_ACTOR_IN_PAINT = 1 << 4 /* Used to avoid recursion */
|
||||
} ClutterPrivateFlags;
|
||||
|
||||
typedef enum {
|
||||
@ -122,7 +124,6 @@ ClutterMainContext *clutter_context_get_default (void);
|
||||
#define I_(str) (g_intern_static_string ((str)))
|
||||
|
||||
/* stage manager */
|
||||
|
||||
struct _ClutterStageManager
|
||||
{
|
||||
GObject parent_instance;
|
||||
@ -135,17 +136,22 @@ void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
||||
void _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage);
|
||||
|
||||
/* vfuncs implemnted by backend */
|
||||
/* stage */
|
||||
|
||||
void _clutter_stage_set_window (ClutterStage *stage,
|
||||
ClutterStageWindow *stage_window);
|
||||
ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage);
|
||||
ClutterStageWindow *_clutter_stage_get_default_window (void);
|
||||
|
||||
/* vfuncs implemented by backend */
|
||||
GType _clutter_backend_impl_get_type (void);
|
||||
|
||||
void _clutter_backend_redraw (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
|
||||
ClutterActor* _clutter_backend_create_stage (ClutterBackend *backend,
|
||||
ClutterActor *_clutter_backend_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error);
|
||||
|
||||
void _clutter_backend_redraw (ClutterBackend *backend,
|
||||
void _clutter_backend_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
|
||||
void _clutter_backend_add_options (ClutterBackend *backend,
|
||||
@ -156,9 +162,6 @@ gboolean _clutter_backend_post_parse (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);
|
||||
|
@ -267,12 +267,11 @@ void
|
||||
_clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
/* this might be called multiple times from a ::dispose, so it
|
||||
* needs to just return without warning
|
||||
*/
|
||||
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);
|
||||
|
||||
|
33
clutter/clutter-stage-window.c
Normal file
33
clutter/clutter-stage-window.c
Normal file
@ -0,0 +1,33 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "clutter-actor.h"
|
||||
#include "clutter-stage-window.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
GType
|
||||
clutter_stage_window_get_type (void)
|
||||
{
|
||||
static GType stage_window_type = 0;
|
||||
|
||||
if (G_UNLIKELY (stage_window_type == 0))
|
||||
{
|
||||
const GTypeInfo stage_window_info = {
|
||||
sizeof (ClutterStageWindowIface),
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
stage_window_type =
|
||||
g_type_register_static (G_TYPE_INTERFACE, I_("ClutterStageWindow"),
|
||||
&stage_window_info, 0);
|
||||
|
||||
g_type_interface_add_prerequisite (stage_window_type,
|
||||
CLUTTER_TYPE_ACTOR);
|
||||
}
|
||||
|
||||
return stage_window_type;
|
||||
}
|
43
clutter/clutter-stage-window.h
Normal file
43
clutter/clutter-stage-window.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef __CLUTTER_STAGE_WINDOW_H__
|
||||
#define __CLUTTER_STAGE_WINDOW_H__
|
||||
|
||||
#include <clutter/clutter-actor.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_STAGE_WINDOW (clutter_stage_window_get_type ())
|
||||
#define CLUTTER_STAGE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_WINDOW, ClutterStageWindow))
|
||||
#define CLUTTER_IS_STAGE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_WINDOW))
|
||||
#define CLUTTER_STAGE_WINDOW_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_STAGE_WINDOW, ClutterStageWindowIface))
|
||||
|
||||
typedef struct _ClutterStageWindow ClutterStageWindow; /* dummy */
|
||||
typedef struct _ClutterStageWindowIface ClutterStageWindowIface;
|
||||
|
||||
struct _ClutterStageWindowIface
|
||||
{
|
||||
GTypeInterface parent_iface;
|
||||
|
||||
ClutterActor *(* get_wrapper) (ClutterStageWindow *stage_window);
|
||||
|
||||
void (* set_title) (ClutterStageWindow *stage_window,
|
||||
const gchar *title);
|
||||
void (* set_fullscreen) (ClutterStageWindow *stage_window,
|
||||
gboolean is_fullscreen);
|
||||
void (* set_cursor_visible) (ClutterStageWindow *stage_window,
|
||||
gboolean cursor_visible);
|
||||
void (* set_user_resizable) (ClutterStageWindow *stage_window,
|
||||
gboolean is_resizable);
|
||||
|
||||
GdkPixbuf * (* draw_to_pixbuf) (ClutterStageWindow *stage_window,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
};
|
||||
|
||||
GType clutter_stage_window_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_WINDOW_H__ */
|
@ -29,6 +29,24 @@
|
||||
*
|
||||
* #ClutterStage is a top level 'window' on which child actors are placed
|
||||
* and manipulated.
|
||||
*
|
||||
* Clutter creates a default stage upon initialization, which can be retrieved
|
||||
* using clutter_stage_get_default(). Clutter always provides the default
|
||||
* stage, unless the backend is unable to create one. The stage returned
|
||||
* by clutter_stage_get_default() is guaranteed to always be the same.
|
||||
*
|
||||
* Backends might provide support for multiple stages. The support for this
|
||||
* feature can be checked at run-time using the clutter_feature_available()
|
||||
* function and the %CLUTTER_FEATURE_STAGE_MULTIPLE flag. If the backend used
|
||||
* supports multiple stages, new #ClutterStage instances can be created
|
||||
* using clutter_stage_new(). These stages must be managed by the developer
|
||||
* using clutter_actor_destroy(), which will take care of destroying all the
|
||||
* actors contained inside them.
|
||||
*
|
||||
* #ClutterStage is a proxy actor, wrapping the backend-specific
|
||||
* implementation of the windowing system. It is possible to subclass
|
||||
* #ClutterStage, as long as every overridden virtual function chains up to
|
||||
* the parent class corresponding function.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@ -45,32 +63,36 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-stage-manager.h"
|
||||
#include "clutter-stage-window.h"
|
||||
#include "clutter-version.h" /* For flavour */
|
||||
#include "clutter-id-pool.h"
|
||||
|
||||
#include "cogl.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
|
||||
G_DEFINE_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
|
||||
|
||||
#define CLUTTER_STAGE_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_STAGE, ClutterStagePrivate))
|
||||
|
||||
struct _ClutterStagePrivate
|
||||
{
|
||||
/* the stage implementation */
|
||||
ClutterActor *impl;
|
||||
|
||||
ClutterColor color;
|
||||
ClutterPerspective perspective;
|
||||
ClutterFog fog;
|
||||
|
||||
gchar *title;
|
||||
ClutterActor *key_focused_actor;
|
||||
|
||||
guint update_idle; /* repaint idler id */
|
||||
|
||||
guint is_fullscreen : 1;
|
||||
guint is_offscreen : 1;
|
||||
guint is_cursor_visible : 1;
|
||||
guint is_user_resizable : 1;
|
||||
guint use_fog : 1;
|
||||
|
||||
gchar *title;
|
||||
ClutterActor *key_focused_actor;
|
||||
|
||||
guint update_idle; /* repaint idler id */
|
||||
};
|
||||
|
||||
enum
|
||||
@ -98,11 +120,37 @@ enum
|
||||
|
||||
static guint stage_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
static void
|
||||
clutter_stage_request_coords (ClutterActor *self,
|
||||
ClutterActorBox *box)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->request_coords (priv->impl, box);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->request_coords (self, box);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_query_coords (ClutterActor *self,
|
||||
ClutterActorBox *box)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->query_coords (priv->impl, box);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_paint (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_PAINT);
|
||||
|
||||
CLUTTER_NOTE (PAINT, "Initializing stage paint");
|
||||
|
||||
cogl_paint_init (&priv->color);
|
||||
|
||||
if (priv->use_fog)
|
||||
@ -113,6 +161,12 @@ clutter_stage_paint (ClutterActor *self)
|
||||
priv->fog.z_far);
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (PAINT, "Proxying the paint to the stage implementation");
|
||||
clutter_actor_paint (priv->impl);
|
||||
|
||||
CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_PAINT);
|
||||
|
||||
/* this will take care of painting every child */
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self);
|
||||
}
|
||||
|
||||
@ -128,6 +182,53 @@ clutter_stage_pick (ClutterActor *self,
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_realize (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
/* then realize the implementation */
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->realize (priv->impl);
|
||||
|
||||
/* set the flag on the wrapper if the implementation was successful */
|
||||
if (CLUTTER_ACTOR_IS_REALIZED (priv->impl))
|
||||
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_unrealize (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
/* unset the flag */
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
/* and then unrealize the implementation */
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->unrealize (priv->impl);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_show (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
clutter_actor_show (priv->impl);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_hide (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
clutter_actor_hide (priv->impl);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->hide (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@ -248,6 +349,24 @@ clutter_stage_get_property (GObject *object,
|
||||
static void
|
||||
clutter_stage_dispose (GObject *object)
|
||||
{
|
||||
ClutterStage *stage = CLUTTER_STAGE (object);
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
|
||||
if (priv->update_idle)
|
||||
{
|
||||
g_source_remove (priv->update_idle);
|
||||
priv->update_idle = 0;
|
||||
}
|
||||
|
||||
_clutter_stage_manager_remove_stage (stage_manager, stage);
|
||||
|
||||
if (priv->impl)
|
||||
{
|
||||
CLUTTER_NOTE (MISC, "Disposing of the stage implementation");
|
||||
g_object_unref (priv->impl);
|
||||
priv->impl = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_parent_class)->dispose (object);
|
||||
}
|
||||
@ -255,11 +374,6 @@ clutter_stage_dispose (GObject *object)
|
||||
static void
|
||||
clutter_stage_finalize (GObject *object)
|
||||
{
|
||||
ClutterStage *stage = CLUTTER_STAGE(object);
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
|
||||
_clutter_stage_manager_remove_stage (stage_manager, stage);
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@ -275,8 +389,14 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
||||
gobject_class->dispose = clutter_stage_dispose;
|
||||
gobject_class->finalize = clutter_stage_finalize;
|
||||
|
||||
actor_class->request_coords = clutter_stage_request_coords;
|
||||
actor_class->query_coords = clutter_stage_query_coords;
|
||||
actor_class->paint = clutter_stage_paint;
|
||||
actor_class->pick = clutter_stage_pick;
|
||||
actor_class->realize = clutter_stage_realize;
|
||||
actor_class->unrealize = clutter_stage_unrealize;
|
||||
actor_class->show = clutter_stage_show;
|
||||
actor_class->hide = clutter_stage_hide;
|
||||
|
||||
/**
|
||||
* ClutterStage:fullscreen:
|
||||
@ -447,12 +567,28 @@ static void
|
||||
clutter_stage_init (ClutterStage *self)
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
ClutterBackend *backend;
|
||||
|
||||
/* a stage is a top-level object */
|
||||
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IS_TOPLEVEL);
|
||||
|
||||
self->priv = priv = CLUTTER_STAGE_GET_PRIVATE (self);
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating stage from the default backend");
|
||||
backend = clutter_get_default_backend ();
|
||||
priv->impl = _clutter_backend_create_stage (backend, self, NULL);
|
||||
if (!priv->impl)
|
||||
{
|
||||
g_warning ("Unable to create a new stage, falling back to the "
|
||||
"default stage.");
|
||||
priv->impl = CLUTTER_ACTOR (_clutter_stage_get_default_window ());
|
||||
|
||||
/* at this point we must have a default stage, or we're screwed */
|
||||
g_assert (priv->impl != NULL);
|
||||
}
|
||||
else
|
||||
g_object_ref_sink (priv->impl);
|
||||
|
||||
priv->is_offscreen = FALSE;
|
||||
priv->is_fullscreen = FALSE;
|
||||
priv->is_user_resizable = FALSE;
|
||||
@ -482,11 +618,12 @@ clutter_stage_init (ClutterStage *self)
|
||||
/**
|
||||
* clutter_stage_get_default:
|
||||
*
|
||||
* Returns the main stage. #ClutterStage is a singleton, so
|
||||
* the stage will be created the first time this function is
|
||||
* Returns the main stage. The default #ClutterStage is a singleton,
|
||||
* so the stage will be created the first time this function is
|
||||
* called (typically, inside clutter_init()); all the subsequent
|
||||
* calls to clutter_stage_get_default() will return the same
|
||||
* instance.
|
||||
* calls to clutter_stage_get_default() will return the same instance.
|
||||
*
|
||||
* Clutter guarantess the existence of the default stage.
|
||||
*
|
||||
* Return value: the main #ClutterStage. You should never
|
||||
* destroy or unref the returned actor.
|
||||
@ -495,8 +632,19 @@ ClutterActor *
|
||||
clutter_stage_get_default (void)
|
||||
{
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
ClutterStage *stage;
|
||||
|
||||
return CLUTTER_ACTOR(clutter_stage_manager_get_default_stage(stage_manager));
|
||||
stage = clutter_stage_manager_get_default_stage (stage_manager);
|
||||
if (G_UNLIKELY (stage == NULL))
|
||||
{
|
||||
/* this will take care of automatically adding the stage
|
||||
* to the stage manager and setting it as the default
|
||||
*/
|
||||
stage = g_object_new (CLUTTER_TYPE_STAGE, NULL);
|
||||
g_object_ref_sink (stage);
|
||||
}
|
||||
|
||||
return CLUTTER_ACTOR (stage);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -516,10 +664,8 @@ clutter_stage_set_color (ClutterStage *stage,
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
priv = stage->priv;
|
||||
priv->color.red = color->red;
|
||||
priv->color.green = color->green;
|
||||
priv->color.blue = color->blue;
|
||||
priv->color.alpha = color->alpha;
|
||||
|
||||
priv->color = *color;
|
||||
|
||||
if (CLUTTER_ACTOR_IS_VISIBLE (stage))
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||
@ -545,10 +691,7 @@ clutter_stage_get_color (ClutterStage *stage,
|
||||
|
||||
priv = stage->priv;
|
||||
|
||||
color->red = priv->color.red;
|
||||
color->green = priv->color.green;
|
||||
color->blue = priv->color.blue;
|
||||
color->alpha = priv->color.alpha;
|
||||
*color = priv->color;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -572,6 +715,9 @@ clutter_stage_set_perspectivex (ClutterStage *stage,
|
||||
|
||||
priv->perspective = *perspective;
|
||||
|
||||
/* this will cause the viewport to be reset; see
|
||||
* clutter_maybe_setup_viewport() inside clutter-main.c
|
||||
*/
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
|
||||
@ -604,7 +750,7 @@ clutter_stage_get_perspectivex (ClutterStage *stage,
|
||||
* @z_far: the distance from the viewer to the far clipping
|
||||
* plane (always positive)
|
||||
*
|
||||
* Set the stage perspective.
|
||||
* Sets the stage perspective.
|
||||
*
|
||||
* Since: 0.4
|
||||
*/
|
||||
@ -621,11 +767,14 @@ clutter_stage_set_perspective (ClutterStage *stage,
|
||||
|
||||
priv = stage->priv;
|
||||
|
||||
priv->perspective.fovy = CLUTTER_FLOAT_TO_FIXED(fovy);
|
||||
priv->perspective.aspect = CLUTTER_FLOAT_TO_FIXED(aspect);
|
||||
priv->perspective.z_near = CLUTTER_FLOAT_TO_FIXED(z_near);
|
||||
priv->perspective.z_far = CLUTTER_FLOAT_TO_FIXED(z_far);
|
||||
priv->perspective.fovy = CLUTTER_FLOAT_TO_FIXED (fovy);
|
||||
priv->perspective.aspect = CLUTTER_FLOAT_TO_FIXED (aspect);
|
||||
priv->perspective.z_near = CLUTTER_FLOAT_TO_FIXED (z_near);
|
||||
priv->perspective.z_far = CLUTTER_FLOAT_TO_FIXED (z_far);
|
||||
|
||||
/* this will cause the viewport to be reset; see
|
||||
* clutter_maybe_setup_viewport() inside clutter-main.c
|
||||
*/
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
|
||||
@ -688,12 +837,17 @@ clutter_stage_fullscreen (ClutterStage *stage)
|
||||
priv = stage->priv;
|
||||
if (!priv->is_fullscreen)
|
||||
{
|
||||
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
|
||||
ClutterStageWindowIface *iface;
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
|
||||
|
||||
/* Only set if backend implements.
|
||||
* Also see clutter_stage_event() for setting priv->is_fullscreen
|
||||
* on state change event.
|
||||
*/
|
||||
if (CLUTTER_STAGE_GET_CLASS (stage)->set_fullscreen)
|
||||
CLUTTER_STAGE_GET_CLASS (stage)->set_fullscreen (stage, TRUE);
|
||||
if (iface->set_fullscreen)
|
||||
iface->set_fullscreen (impl, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -717,9 +871,17 @@ clutter_stage_unfullscreen (ClutterStage *stage)
|
||||
priv = stage->priv;
|
||||
if (priv->is_fullscreen)
|
||||
{
|
||||
/* Only set if backend implements */
|
||||
if (CLUTTER_STAGE_GET_CLASS (stage)->set_fullscreen)
|
||||
CLUTTER_STAGE_GET_CLASS (stage)->set_fullscreen (stage, FALSE);
|
||||
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
|
||||
ClutterStageWindowIface *iface;
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
|
||||
|
||||
/* Only set if backend implements.
|
||||
* Also see clutter_stage_event() for setting priv->is_fullscreen
|
||||
* on state change event.
|
||||
*/
|
||||
if (iface->set_fullscreen)
|
||||
iface->set_fullscreen (impl, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -744,15 +906,21 @@ clutter_stage_set_user_resizable (ClutterStage *stage,
|
||||
priv = stage->priv;
|
||||
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_STAGE_USER_RESIZE)
|
||||
&& priv->is_user_resizable != resizable
|
||||
&& CLUTTER_STAGE_GET_CLASS (stage)->set_user_resize)
|
||||
&& priv->is_user_resizable != resizable)
|
||||
{
|
||||
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
|
||||
ClutterStageWindowIface *iface;
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
|
||||
if (iface->set_user_resizable)
|
||||
{
|
||||
priv->is_user_resizable = resizable;
|
||||
|
||||
CLUTTER_STAGE_GET_CLASS (stage)->set_user_resize (stage, resizable);
|
||||
iface->set_user_resizable (impl, resizable);
|
||||
|
||||
g_object_notify (G_OBJECT (stage), "user-resizable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -788,14 +956,20 @@ clutter_stage_show_cursor (ClutterStage *stage)
|
||||
|
||||
priv = stage->priv;
|
||||
if (!priv->is_cursor_visible)
|
||||
{
|
||||
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
|
||||
ClutterStageWindowIface *iface;
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
|
||||
if (iface->set_cursor_visible)
|
||||
{
|
||||
priv->is_cursor_visible = TRUE;
|
||||
|
||||
if (CLUTTER_STAGE_GET_CLASS (stage)->set_cursor_visible)
|
||||
CLUTTER_STAGE_GET_CLASS (stage)->set_cursor_visible (stage, TRUE);
|
||||
iface->set_cursor_visible (impl, TRUE);
|
||||
|
||||
g_object_notify (G_OBJECT (stage), "cursor-visible");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -816,13 +990,19 @@ clutter_stage_hide_cursor (ClutterStage *stage)
|
||||
priv = stage->priv;
|
||||
if (priv->is_cursor_visible)
|
||||
{
|
||||
priv->is_cursor_visible = FALSE;
|
||||
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
|
||||
ClutterStageWindowIface *iface;
|
||||
|
||||
if (CLUTTER_STAGE_GET_CLASS (stage)->set_cursor_visible)
|
||||
CLUTTER_STAGE_GET_CLASS (stage)->set_cursor_visible (stage, FALSE);
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
|
||||
if (iface->set_cursor_visible)
|
||||
{
|
||||
priv->is_cursor_visible = TRUE;
|
||||
|
||||
iface->set_cursor_visible (impl, FALSE);
|
||||
|
||||
g_object_notify (G_OBJECT (stage), "cursor-visible");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -837,8 +1017,9 @@ clutter_stage_hide_cursor (ClutterStage *stage)
|
||||
*
|
||||
* Gets a pixel based representation of the current rendered stage.
|
||||
*
|
||||
* Return value: pixel representation as a #GdkPixbuf
|
||||
**/
|
||||
* Return value: pixel representation as a #GdkPixbuf, or %NULL if
|
||||
* the backend does not support this operation
|
||||
*/
|
||||
GdkPixbuf *
|
||||
clutter_stage_snapshot (ClutterStage *stage,
|
||||
gint x,
|
||||
@ -846,14 +1027,17 @@ clutter_stage_snapshot (ClutterStage *stage,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
ClutterStageClass *klass;
|
||||
ClutterStageWindow *impl;
|
||||
ClutterStageWindowIface *iface;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
|
||||
g_return_val_if_fail (x >= 0 && y >= 0, NULL);
|
||||
|
||||
klass = CLUTTER_STAGE_GET_CLASS (stage);
|
||||
if (klass->draw_to_pixbuf)
|
||||
return klass->draw_to_pixbuf (stage, x, y, width, height);
|
||||
impl = CLUTTER_STAGE_WINDOW (stage->priv->impl);
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
|
||||
|
||||
if (iface->draw_to_pixbuf)
|
||||
return iface->draw_to_pixbuf (impl, x, y, width, height);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -883,8 +1067,9 @@ clutter_stage_get_actor_at_pos (ClutterStage *stage,
|
||||
* @event: a #ClutterEvent
|
||||
*
|
||||
* This function is used to emit an event on the main stage.
|
||||
*
|
||||
* You should rarely need to use this function, except for
|
||||
* synthetising events.
|
||||
* synthetised events.
|
||||
*
|
||||
* Return value: the return value from the signal emission
|
||||
*
|
||||
@ -960,6 +1145,7 @@ clutter_stage_set_title (ClutterStage *stage,
|
||||
const gchar *title)
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
ClutterStageWindow *impl;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
@ -968,8 +1154,8 @@ clutter_stage_set_title (ClutterStage *stage,
|
||||
g_free (priv->title);
|
||||
priv->title = g_strdup (title);
|
||||
|
||||
if (CLUTTER_STAGE_GET_CLASS (stage)->set_title)
|
||||
CLUTTER_STAGE_GET_CLASS (stage)->set_title (stage, priv->title);
|
||||
impl = CLUTTER_STAGE_WINDOW (priv->impl);
|
||||
CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->set_title (impl, priv->title);
|
||||
|
||||
g_object_notify (G_OBJECT (stage), "title");
|
||||
}
|
||||
@ -1373,7 +1559,7 @@ clutter_fog_get_type (void)
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_create_new:
|
||||
* clutter_stage_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
|
||||
@ -1388,15 +1574,13 @@ clutter_fog_get_type (void)
|
||||
*
|
||||
* 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.
|
||||
* programmatically close the returned stage.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
ClutterActor*
|
||||
clutter_stage_create_new (void)
|
||||
ClutterActor *
|
||||
clutter_stage_new (void)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
GError *error = NULL;
|
||||
ClutterActor *retval;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE))
|
||||
@ -1407,15 +1591,11 @@ clutter_stage_create_new (void)
|
||||
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;
|
||||
}
|
||||
retval = g_object_new (CLUTTER_TYPE_STAGE, NULL);
|
||||
if (retval)
|
||||
return g_object_ref_sink (retval);
|
||||
|
||||
return retval;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1431,24 +1611,23 @@ clutter_stage_create_new (void)
|
||||
void
|
||||
clutter_stage_ensure_current (ClutterStage *stage)
|
||||
{
|
||||
ClutterMainContext *ctx;
|
||||
ClutterMainContext *ctx = clutter_context_get_default ();
|
||||
|
||||
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)
|
||||
redraw_update_idle (gpointer user_data)
|
||||
{
|
||||
ClutterStage *stage = CLUTTER_STAGE(data);
|
||||
ClutterStage *stage = user_data;
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
|
||||
if (stage->priv->update_idle)
|
||||
if (priv->update_idle)
|
||||
{
|
||||
g_source_remove (stage->priv->update_idle);
|
||||
stage->priv->update_idle = 0;
|
||||
g_source_remove (priv->update_idle);
|
||||
priv->update_idle = 0;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (MULTISTAGE, "redrawing via idle for stage:%p", stage);
|
||||
@ -1461,8 +1640,10 @@ redraw_update_idle (gpointer data)
|
||||
* clutter_stage_queue_redraw:
|
||||
* @stage: the #ClutterStage
|
||||
*
|
||||
* Queues a redraw for the passed stage. Note applications should call
|
||||
* #clutter_actor_queue_redraw over this.
|
||||
* Queues a redraw for the passed stage.
|
||||
*
|
||||
* <note>Applications should call clutter_actor_queue_redraw() and not
|
||||
* this function.</note>
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
@ -1483,3 +1664,32 @@ clutter_stage_queue_redraw (ClutterStage *stage)
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_set_window (ClutterStage *stage,
|
||||
ClutterStageWindow *stage_window)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (stage_window));
|
||||
|
||||
if (stage->priv->impl)
|
||||
g_object_unref (stage->priv->impl);
|
||||
|
||||
stage->priv->impl = CLUTTER_ACTOR (stage_window);
|
||||
}
|
||||
|
||||
ClutterStageWindow *
|
||||
_clutter_stage_get_window (ClutterStage *stage)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
|
||||
|
||||
return CLUTTER_STAGE_WINDOW (stage->priv->impl);
|
||||
}
|
||||
|
||||
ClutterStageWindow *
|
||||
_clutter_stage_get_default_window (void)
|
||||
{
|
||||
ClutterActor *stage = clutter_stage_get_default ();
|
||||
|
||||
return _clutter_stage_get_window (CLUTTER_STAGE (stage));
|
||||
}
|
||||
|
@ -99,22 +99,7 @@ struct _ClutterStageClass
|
||||
ClutterGroupClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
/* vfuncs, not signals */
|
||||
void (* set_fullscreen) (ClutterStage *stage,
|
||||
gboolean fullscreen);
|
||||
void (* set_cursor_visible) (ClutterStage *stage,
|
||||
gboolean visible);
|
||||
GdkPixbuf* (* draw_to_pixbuf) (ClutterStage *stage,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
void (* set_title) (ClutterStage *stage,
|
||||
const gchar *title);
|
||||
void (* set_user_resize) (ClutterStage *stage,
|
||||
gboolean value);
|
||||
|
||||
/* events */
|
||||
/* signals */
|
||||
void (* fullscreen) (ClutterStage *stage);
|
||||
void (* unfullscreen) (ClutterStage *stage);
|
||||
void (* activate) (ClutterStage *stage);
|
||||
@ -175,6 +160,8 @@ GType clutter_fog_get_type (void) G_GNUC_CONST;
|
||||
GType clutter_stage_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *clutter_stage_get_default (void);
|
||||
ClutterActor *clutter_stage_new (void);
|
||||
|
||||
void clutter_stage_set_color (ClutterStage *stage,
|
||||
const ClutterColor *color);
|
||||
void clutter_stage_get_color (ClutterStage *stage,
|
||||
@ -233,15 +220,12 @@ void clutter_stage_get_fogx (ClutterStage *stage,
|
||||
gdouble clutter_stage_get_resolution (ClutterStage *stage);
|
||||
ClutterFixed clutter_stage_get_resolutionx (ClutterStage *stage);
|
||||
|
||||
/* New experiental calls */
|
||||
void clutter_stage_set_key_focus (ClutterStage *stage,
|
||||
ClutterActor *actor);
|
||||
ClutterActor * clutter_stage_get_key_focus (ClutterStage *stage);
|
||||
|
||||
ClutterActor* clutter_stage_create_new (void);
|
||||
|
||||
/* New experiental calls */
|
||||
void clutter_stage_ensure_current (ClutterStage *stage);
|
||||
|
||||
void clutter_stage_queue_redraw (ClutterStage *stage);
|
||||
|
||||
/* Commodity macro */
|
||||
|
@ -23,9 +23,10 @@ clutter_backend_egl_post_parse (ClutterBackend *backend,
|
||||
{
|
||||
EGLBoolean status;
|
||||
|
||||
backend_egl->edpy = eglGetDisplay((NativeDisplayType)backend_x11->xdpy);
|
||||
backend_egl->edpy =
|
||||
eglGetDisplay ((NativeDisplayType) backend_x11->xdpy);
|
||||
|
||||
status = eglInitialize(backend_egl->edpy,
|
||||
status = eglInitialize (backend_egl->edpy,
|
||||
&backend_egl->egl_version_major,
|
||||
&backend_egl->egl_version_minor);
|
||||
|
||||
@ -47,17 +48,80 @@ clutter_backend_egl_post_parse (ClutterBackend *backend,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_egl_redraw (ClutterBackend *backend)
|
||||
clutter_backend_egl_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
|
||||
if (stage == NULL)
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Clearing EGL context");
|
||||
eglMakeCurrent (backend_egl->edpy,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterStageWindow *impl;
|
||||
ClutterStageEGL *stage_egl;
|
||||
ClutterStageX11 *stage_x11;
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11(backend_x11->stage);
|
||||
stage_egl = CLUTTER_STAGE_EGL(backend_x11->stage);
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
g_assert (impl != NULL);
|
||||
|
||||
clutter_actor_paint (CLUTTER_ACTOR(stage_egl));
|
||||
CLUTTER_NOTE (MULTISTAGE, "Setting context for stage of type %s [%p]",
|
||||
g_type_name (G_OBJECT_TYPE (impl)),
|
||||
impl);
|
||||
|
||||
stage_egl = CLUTTER_STAGE_EGL (impl);
|
||||
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
||||
|
||||
g_return_if_fail (backend_egl->egl_context != NULL);
|
||||
|
||||
/* we might get here inside the final dispose cycle, so we
|
||||
* need to handle this gracefully
|
||||
*/
|
||||
if (stage_x11->xwin == None ||
|
||||
stage_egl->egl_surface == EGL_NO_SURFACE)
|
||||
{
|
||||
CLUTTER_NOTE (MULTISTAGE,
|
||||
"Received a stale stage, clearing all context");
|
||||
|
||||
eglMakeCurrent (backend_egl->edpy,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
}
|
||||
else
|
||||
eglMakeCurrent (backend_egl->edpy,
|
||||
stage_egl->egl_surface,
|
||||
stage_egl->egl_surface,
|
||||
backend_egl->egl_context);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_egl_redraw (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
ClutterStageWindow *impl;
|
||||
ClutterStageEGL *stage_egl;
|
||||
ClutterStageX11 *stage_x11;
|
||||
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
if (!impl)
|
||||
return;
|
||||
|
||||
g_assert (CLUTTER_IS_STAGE_EGL (impl));
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
||||
stage_egl = CLUTTER_STAGE_EGL (impl);
|
||||
|
||||
/* this will cause the stage implementation to be painted as well */
|
||||
clutter_actor_paint (CLUTTER_ACTOR (stage));
|
||||
|
||||
/* Why this paint is done in backend as likely GL windowing system
|
||||
* specific calls, like swapping buffers.
|
||||
@ -88,6 +152,12 @@ clutter_backend_egl_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
|
||||
|
||||
if (backend_egl->egl_context)
|
||||
{
|
||||
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
|
||||
backend_egl->egl_context = NULL;
|
||||
}
|
||||
|
||||
if (backend_egl->edpy)
|
||||
{
|
||||
eglTerminate (backend_egl->edpy);
|
||||
@ -133,29 +203,28 @@ clutter_backend_egl_get_features (ClutterBackend *backend)
|
||||
"EGL_VENDOR: %s\n",
|
||||
"EGL_VERSION: %s\n",
|
||||
"EGL_EXTENSIONS: %s\n",
|
||||
glGetString(GL_VENDOR),
|
||||
glGetString(GL_RENDERER),
|
||||
glGetString(GL_VERSION),
|
||||
eglQueryString(backend_egl->edpy, EGL_VENDOR),
|
||||
eglQueryString(backend_egl->edpy, EGL_VERSION),
|
||||
eglQueryString(backend_egl->edpy, EGL_EXTENSIONS));
|
||||
glGetString (GL_VENDOR),
|
||||
glGetString (GL_RENDERER),
|
||||
glGetString (GL_VERSION),
|
||||
eglQueryString (backend_egl->edpy, EGL_VENDOR),
|
||||
eglQueryString (backend_egl->edpy, EGL_VERSION),
|
||||
eglQueryString (backend_egl->edpy, EGL_EXTENSIONS));
|
||||
|
||||
/* We can actually resize too */
|
||||
return CLUTTER_FEATURE_STAGE_CURSOR|CLUTTER_FEATURE_STAGE_MULTIPLE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_backend_egl_init_stage (ClutterBackend *backend,
|
||||
static ClutterActor *
|
||||
clutter_backend_egl_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
|
||||
if (!backend_x11->stage)
|
||||
{
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterActor *stage;
|
||||
CLUTTER_NOTE (BACKEND, "Creating stage of type `%s'",
|
||||
g_type_name (CLUTTER_STAGE_TYPE));
|
||||
|
||||
stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
|
||||
stage = g_object_new (CLUTTER_STAGE_TYPE, NULL);
|
||||
|
||||
/* copy backend data into the stage */
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
@ -163,17 +232,18 @@ clutter_backend_egl_init_stage (ClutterBackend *backend,
|
||||
stage_x11->xwin_root = backend_x11->xwin_root;
|
||||
stage_x11->xscreen = backend_x11->xscreen_num;
|
||||
stage_x11->backend = backend_x11;
|
||||
stage_x11->wrapper = wrapper;
|
||||
|
||||
CLUTTER_NOTE (MISC, "X11 stage created (display:%p, screen:%d, root:%u)",
|
||||
/* set the pointer back into the wrapper */
|
||||
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage));
|
||||
|
||||
CLUTTER_NOTE (MISC, "EGLX stage created (display:%p, screen:%d, root:%u)",
|
||||
stage_x11->xdpy,
|
||||
stage_x11->xscreen,
|
||||
(unsigned int) stage_x11->xwin_root);
|
||||
|
||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||
|
||||
backend_x11->stage = g_object_ref_sink (stage);
|
||||
}
|
||||
|
||||
clutter_actor_realize (backend_x11->stage);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (backend_x11->stage))
|
||||
@ -181,10 +251,11 @@ clutter_backend_egl_init_stage (ClutterBackend *backend,
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_INTERNAL,
|
||||
"Unable to realize the main stage");
|
||||
return FALSE;
|
||||
g_object_unref (stage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return stage;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -200,13 +271,14 @@ clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
|
||||
backend_class->post_parse = clutter_backend_egl_post_parse;
|
||||
backend_class->redraw = clutter_backend_egl_redraw;
|
||||
backend_class->get_features = clutter_backend_egl_get_features;
|
||||
backend_class->init_stage = clutter_backend_egl_init_stage;
|
||||
backend_class->create_stage = clutter_backend_egl_create_stage;
|
||||
backend_class->ensure_context = clutter_backend_egl_ensure_context;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
|
||||
{
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
GType
|
||||
|
@ -52,7 +52,11 @@ struct _ClutterBackendEGL
|
||||
|
||||
/* EGL Specific */
|
||||
EGLDisplay edpy;
|
||||
gint egl_version_major, egl_version_minor;
|
||||
EGLSurface egl_surface;
|
||||
EGLContext egl_context;
|
||||
|
||||
gint egl_version_major;
|
||||
gint egl_version_minor;
|
||||
|
||||
};
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-backend-egl.h"
|
||||
#include "clutter-stage-egl.h"
|
||||
#include "clutter-eglx.h"
|
||||
|
||||
@ -14,8 +15,17 @@
|
||||
#include "../clutter-private.h"
|
||||
#include "../clutter-debug.h"
|
||||
#include "../clutter-units.h"
|
||||
#include "../clutter-container.h"
|
||||
#include "../clutter-stage.h"
|
||||
#include "../clutter-stage-window.h"
|
||||
|
||||
G_DEFINE_TYPE (ClutterStageEGL, clutter_stage_egl, CLUTTER_TYPE_STAGE_X11);
|
||||
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
|
||||
clutter_stage_egl,
|
||||
CLUTTER_TYPE_STAGE_X11,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
||||
clutter_stage_window_iface_init));
|
||||
|
||||
static void
|
||||
clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
@ -26,17 +36,19 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
|
||||
CLUTTER_MARK();
|
||||
|
||||
g_object_get (actor, "offscreen", &was_offscreen, NULL);
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
|
||||
clutter_x11_trap_x_errors ()
|
||||
|
||||
if (G_UNLIKELY (was_offscreen))
|
||||
{
|
||||
/* No support as yet for this */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stage_x11->xwin != None)
|
||||
if (!stage_X11->is_foreign_xwin && stage_x11->xwin != None)
|
||||
{
|
||||
XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
|
||||
stage_x11->xwin = None;
|
||||
@ -46,17 +58,18 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
}
|
||||
|
||||
if (stage_egl->egl_surface)
|
||||
eglDestroySurface (clutter_eglx_display(), stage_egl->egl_surface);
|
||||
stage_egl->egl_surface = NULL;
|
||||
{
|
||||
eglDestroySurface (clutter_eglx_display (), stage_egl->egl_surface);
|
||||
stage_egl->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
if (stage_egl->egl_context)
|
||||
eglDestroyContext (clutter_eglx_display(), stage_egl->egl_context);
|
||||
stage_egl->egl_context = NULL;
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
|
||||
eglMakeCurrent (clutter_eglx_display(),
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
/* XSync (stage_x11->xdpy, False); */
|
||||
|
||||
stage_egl->egl_context = None;
|
||||
clutter_x11_untrap_x_errors ();
|
||||
|
||||
CLUTTER_MARK ();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -64,45 +77,48 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||
|
||||
ClutterBackendEGL *backend_egl;
|
||||
EGLConfig configs[2];
|
||||
EGLint config_count;
|
||||
EGLBoolean status;
|
||||
|
||||
gboolean is_offscreen;
|
||||
gboolean is_offscreen = FALSE;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Realizing main stage");
|
||||
|
||||
g_object_get (actor, "offscreen", &is_offscreen, NULL);
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
|
||||
|
||||
backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ());
|
||||
|
||||
if (G_LIKELY (!is_offscreen))
|
||||
{
|
||||
EGLint cfg_attribs[] = { EGL_BUFFER_SIZE, EGL_DONT_CARE,
|
||||
EGLint cfg_attribs[] = {
|
||||
EGL_BUFFER_SIZE, EGL_DONT_CARE,
|
||||
EGL_RED_SIZE, 5,
|
||||
EGL_GREEN_SIZE, 6,
|
||||
EGL_BLUE_SIZE, 5,
|
||||
EGL_NONE };
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
status = eglGetConfigs (clutter_eglx_display(),
|
||||
status = eglGetConfigs (backend_egl->edpy,
|
||||
configs,
|
||||
2,
|
||||
&config_count);
|
||||
|
||||
if (status != EGL_TRUE)
|
||||
g_warning ("eglGetConfigs");
|
||||
g_warning ("eglGetConfigs failed");
|
||||
|
||||
status = eglChooseConfig (clutter_eglx_display(),
|
||||
status = eglChooseConfig (backend_egl->edpy,
|
||||
cfg_attribs,
|
||||
configs,
|
||||
sizeof configs / sizeof configs[0],
|
||||
G_N_ELEMENTS (configs),
|
||||
&config_count);
|
||||
|
||||
if (status != EGL_TRUE)
|
||||
g_warning ("eglChooseConfig");
|
||||
g_warning ("eglChooseConfig failed");
|
||||
|
||||
if (stage_x11->xwin == None)
|
||||
stage_x11->xwin
|
||||
= XCreateSimpleWindow(stage_x11->xdpy,
|
||||
stage_x11->xwin =
|
||||
XCreateSimpleWindow (stage_x11->xdpy,
|
||||
stage_x11->xwin_root,
|
||||
0, 0,
|
||||
stage_x11->xwin_width,
|
||||
@ -111,69 +127,68 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
WhitePixel (stage_x11->xdpy,
|
||||
stage_x11->xscreen));
|
||||
|
||||
XSelectInput(stage_x11->xdpy,
|
||||
stage_x11->xwin,
|
||||
XSelectInput (stage_x11->xdpy, stage_x11->xwin,
|
||||
StructureNotifyMask
|
||||
|ExposureMask
|
||||
| ExposureMask
|
||||
/* FIXME: we may want to eplicity enable MotionMask */
|
||||
|PointerMotionMask
|
||||
|KeyPressMask
|
||||
|KeyReleaseMask
|
||||
|ButtonPressMask
|
||||
|ButtonReleaseMask
|
||||
|PropertyChangeMask);
|
||||
| PointerMotionMask
|
||||
| KeyPressMask
|
||||
| KeyReleaseMask
|
||||
| ButtonPressMask
|
||||
| ButtonReleaseMask
|
||||
| PropertyChangeMask);
|
||||
|
||||
if (stage_egl->egl_context)
|
||||
eglDestroyContext (clutter_eglx_display(), stage_egl->egl_context);
|
||||
if (stage_egl->egl_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
eglDestroySurface (backend_egl->edpy, stage_egl->egl_surface);
|
||||
stage_egl->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
if (stage_egl->egl_surface)
|
||||
eglDestroySurface (clutter_eglx_display(), stage_egl->egl_surface);
|
||||
|
||||
stage_egl->egl_surface
|
||||
= eglCreateWindowSurface (clutter_eglx_display(),
|
||||
stage_egl->egl_surface =
|
||||
eglCreateWindowSurface (backend_egl->edpy,
|
||||
configs[0],
|
||||
(NativeWindowType)stage_x11->xwin,
|
||||
(NativeWindowType) stage_x11->xwin,
|
||||
NULL);
|
||||
|
||||
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
||||
g_warning ("eglCreateWindowSurface");
|
||||
|
||||
stage_egl->egl_context = eglCreateContext (clutter_eglx_display(),
|
||||
configs[0],
|
||||
EGL_NO_CONTEXT,
|
||||
NULL);
|
||||
|
||||
if (stage_egl->egl_context == EGL_NO_CONTEXT)
|
||||
g_warning ("eglCreateContext");
|
||||
|
||||
status = eglMakeCurrent (clutter_eglx_display(),
|
||||
stage_egl->egl_surface,
|
||||
stage_egl->egl_surface,
|
||||
stage_egl->egl_context);
|
||||
|
||||
if (status != EGL_TRUE)
|
||||
g_warning ("eglMakeCurrent");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning("EGL Backend does not yet support offscreen rendering\n");
|
||||
g_critical ("Unable to create an EGL surface");
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
if (G_UNLIKELY (backend_egl->egl_context == None))
|
||||
{
|
||||
CLUTTER_NOTE (GL, "Creating EGL Context");
|
||||
|
||||
static GdkPixbuf*
|
||||
clutter_stage_egl_draw_to_pixbuf (ClutterStage *stage,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
g_warning ("Stage of type `%s' do not support ClutterStage::draw_to_pixbuf",
|
||||
G_OBJECT_TYPE_NAME (stage));
|
||||
return NULL;
|
||||
backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
|
||||
configs[0],
|
||||
EGL_NO_CONTEXT,
|
||||
NULL);
|
||||
|
||||
if (backend_egl->egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
g_critical ("Unable to create a suitable EGL context");
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning("EGLX Backend does not support offscreen rendering");
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -188,24 +203,40 @@ clutter_stage_egl_dispose (GObject *gobject)
|
||||
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
clutter_stage_egl_draw_to_pixbuf (ClutterStageWindow *stage_window,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
g_warning ("Stages of type `%s' do not support "
|
||||
"ClutterStageWindow::draw_to_pixbuf",
|
||||
G_OBJECT_TYPE_NAME (stage));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
||||
{
|
||||
iface->draw_to_pixbuf = clutter_stage_egl_draw_to_pixbuf;
|
||||
|
||||
/* the rest is inherited from ClutterStageX11 */
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = clutter_stage_egl_dispose;
|
||||
|
||||
actor_class->realize = clutter_stage_egl_realize;
|
||||
actor_class->unrealize = clutter_stage_egl_unrealize;
|
||||
stage_class->draw_to_pixbuf = clutter_stage_egl_draw_to_pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_egl_init (ClutterStageEGL *stage)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,7 +28,6 @@ struct _ClutterStageEGL
|
||||
ClutterStageX11 parent_instance;
|
||||
|
||||
EGLSurface egl_surface;
|
||||
EGLContext egl_context;
|
||||
};
|
||||
|
||||
struct _ClutterStageEGLClass
|
||||
|
@ -173,6 +173,15 @@ clutter_backend_glx_finalize (GObject *gobject)
|
||||
static void
|
||||
clutter_backend_glx_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (gobject);
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
|
||||
|
||||
if (backend_glx->gl_context)
|
||||
{
|
||||
glXDestroyContext (backend_x11->xdpy, backend_glx->gl_context);
|
||||
backend_glx->gl_context = None;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_backend_glx_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@ -214,10 +223,13 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
||||
const gchar *glx_extensions = NULL;
|
||||
ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_MULTIPLE;
|
||||
ClutterFeatureFlags flags;
|
||||
|
||||
/* this will make sure that the GL context exists and its
|
||||
* bound to a drawable
|
||||
flags = clutter_backend_x11_get_features (backend);
|
||||
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
|
||||
|
||||
/* this will make sure that the GL context exists and
|
||||
* it's bound to a drawable
|
||||
*/
|
||||
g_assert (backend_glx->gl_context != None);
|
||||
g_assert (glXGetCurrentDrawable () != None);
|
||||
@ -344,36 +356,56 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
|
||||
|
||||
CLUTTER_NOTE (MISC, "backend features checked");
|
||||
|
||||
return flags|clutter_backend_x11_get_features (backend);
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterBackendGLX *backend_glx;
|
||||
ClutterStageGLX *stage_glx;
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterBackendX11 *backend_x11;
|
||||
|
||||
if (stage == NULL)
|
||||
{
|
||||
backend_x11 = CLUTTER_BACKEND_X11(backend);
|
||||
ClutterBackendX11 *backend_x11;
|
||||
|
||||
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
CLUTTER_NOTE (MULTISTAGE, "Clearing all context");
|
||||
|
||||
glXMakeCurrent (backend_x11->xdpy, None, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
stage_glx = CLUTTER_STAGE_GLX(stage);
|
||||
stage_x11 = CLUTTER_STAGE_X11(stage);
|
||||
backend_glx = CLUTTER_BACKEND_GLX(backend);
|
||||
ClutterBackendGLX *backend_glx;
|
||||
ClutterStageGLX *stage_glx;
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterStageWindow *impl;
|
||||
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
g_assert (impl != NULL);
|
||||
|
||||
CLUTTER_NOTE (MULTISTAGE, "Setting context for stage of type %s [%p]",
|
||||
g_type_name (G_OBJECT_TYPE (impl)),
|
||||
impl);
|
||||
|
||||
stage_glx = CLUTTER_STAGE_GLX (impl);
|
||||
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
||||
backend_glx = CLUTTER_BACKEND_GLX (backend);
|
||||
|
||||
g_return_if_fail (stage_x11->xwin != None);
|
||||
g_return_if_fail (backend_glx->gl_context != None);
|
||||
|
||||
CLUTTER_NOTE (MULTISTAGE, "setting context for stage:%p", stage );
|
||||
/* we might get here inside the final dispose cycle, so we
|
||||
* need to handle this gracefully
|
||||
*/
|
||||
if (stage_x11->xwin == None)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11;
|
||||
|
||||
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
CLUTTER_NOTE (MULTISTAGE,
|
||||
"Received a stale stage, clearing all context");
|
||||
|
||||
glXMakeCurrent (backend_x11->xdpy, None, NULL);
|
||||
}
|
||||
else
|
||||
glXMakeCurrent (stage_x11->xdpy,
|
||||
stage_x11->xwin,
|
||||
backend_glx->gl_context);
|
||||
@ -381,22 +413,31 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_redraw (ClutterBackend *backend, ClutterStage *stage)
|
||||
clutter_backend_glx_redraw (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterStageGLX *stage_glx;
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterStageWindow *impl;
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11(stage);
|
||||
stage_glx = CLUTTER_STAGE_GLX(stage);
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
if (!impl)
|
||||
return;
|
||||
|
||||
clutter_actor_paint (CLUTTER_ACTOR (stage_glx));
|
||||
g_assert (CLUTTER_IS_STAGE_GLX (impl));
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
||||
stage_glx = CLUTTER_STAGE_GLX (impl);
|
||||
|
||||
/* this will cause the stage implementation to be painted */
|
||||
clutter_actor_paint (CLUTTER_ACTOR (stage));
|
||||
|
||||
/* Why this paint is done in backend as likely GL windowing system
|
||||
* specific calls, like swapping buffers.
|
||||
*/
|
||||
if (stage_x11->xwin)
|
||||
{
|
||||
clutter_backend_glx_wait_for_vblank (CLUTTER_BACKEND_GLX(backend));
|
||||
clutter_backend_glx_wait_for_vblank (CLUTTER_BACKEND_GLX (backend));
|
||||
glXSwapBuffers (stage_x11->xdpy, stage_x11->xwin);
|
||||
}
|
||||
else
|
||||
@ -409,12 +450,16 @@ clutter_backend_glx_redraw (ClutterBackend *backend, ClutterStage *stage)
|
||||
|
||||
static ClutterActor*
|
||||
clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterActor *stage;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating stage of type `%s'",
|
||||
g_type_name (CLUTTER_STAGE_TYPE));
|
||||
|
||||
stage = g_object_new (CLUTTER_STAGE_TYPE, NULL);
|
||||
|
||||
/* copy backend data into the stage */
|
||||
@ -423,8 +468,12 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
stage_x11->xwin_root = backend_x11->xwin_root;
|
||||
stage_x11->xscreen = backend_x11->xscreen_num;
|
||||
stage_x11->backend = backend_x11;
|
||||
stage_x11->wrapper = wrapper;
|
||||
|
||||
CLUTTER_NOTE (MISC, "X11 stage created (display:%p, screen:%d, root:%u)",
|
||||
/* set the pointer back into the wrapper */
|
||||
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage));
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "GLX stage created (display:%p, screen:%d, root:%u)",
|
||||
stage_x11->xdpy,
|
||||
stage_x11->xscreen,
|
||||
(unsigned int) stage_x11->xwin_root);
|
||||
@ -432,6 +481,10 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
/* needed ? */
|
||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||
|
||||
/* FIXME - is this needed? we should call realize inside the clutter
|
||||
* init sequence for the default stage, and let the usual realization
|
||||
* sequence be used for any other stage
|
||||
*/
|
||||
clutter_actor_realize (stage);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
@ -445,7 +498,6 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
return stage;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
|
||||
{
|
||||
@ -468,7 +520,7 @@ clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
|
||||
static void
|
||||
clutter_backend_glx_init (ClutterBackendGLX *backend_glx)
|
||||
{
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
/* every backend must implement this function */
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "../clutter-group.h"
|
||||
#include "../clutter-container.h"
|
||||
#include "../clutter-stage.h"
|
||||
#include "../clutter-stage-window.h"
|
||||
|
||||
#include "cogl.h"
|
||||
|
||||
@ -48,21 +49,25 @@
|
||||
|
||||
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
|
||||
|
||||
G_DEFINE_TYPE (ClutterStageGLX, clutter_stage_glx, CLUTTER_TYPE_STAGE_X11);
|
||||
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX,
|
||||
clutter_stage_glx,
|
||||
CLUTTER_TYPE_STAGE_X11,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
||||
clutter_stage_window_iface_init));
|
||||
|
||||
static void
|
||||
clutter_stage_glx_unrealize (ClutterActor *actor)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
||||
|
||||
/* Note unrealize should free up any backend stage related resources */
|
||||
|
||||
gboolean was_offscreen;
|
||||
|
||||
/* Note unrealize should free up any backend stage related resources */
|
||||
CLUTTER_MARK();
|
||||
|
||||
g_object_get (actor, "offscreen", &was_offscreen, NULL);
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL);
|
||||
|
||||
/* Chain up so all children get unrealized, needed to move texture data
|
||||
* across contexts
|
||||
@ -100,7 +105,7 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
|
||||
}
|
||||
|
||||
/* As unrealised the context will now get cleared */
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE(stage_glx));
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
|
||||
XSync (stage_x11->xdpy, False);
|
||||
|
||||
@ -119,9 +124,9 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
|
||||
CLUTTER_NOTE (MISC, "Realizing main stage");
|
||||
|
||||
g_object_get (actor, "offscreen", &is_offscreen, NULL);
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
|
||||
|
||||
backend_glx = CLUTTER_BACKEND_GLX(clutter_get_default_backend());
|
||||
backend_glx = CLUTTER_BACKEND_GLX (clutter_get_default_backend ());
|
||||
|
||||
if (G_LIKELY (!is_offscreen))
|
||||
{
|
||||
@ -137,8 +142,10 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
};
|
||||
|
||||
if (stage_x11->xvisinfo)
|
||||
{
|
||||
XFree (stage_x11->xvisinfo);
|
||||
stage_x11->xvisinfo = NULL;
|
||||
stage_x11->xvisinfo = None;
|
||||
}
|
||||
|
||||
/* The following check seems strange */
|
||||
if (stage_x11->xvisinfo == None)
|
||||
@ -148,6 +155,8 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
if (!stage_x11->xvisinfo)
|
||||
{
|
||||
g_critical ("Unable to find suitable GL visual.");
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
@ -193,7 +202,6 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
|
||||
/* no user resize.. */
|
||||
clutter_stage_x11_fix_window_size (stage_x11);
|
||||
|
||||
clutter_stage_x11_set_wm_protocols (stage_x11);
|
||||
|
||||
if (backend_glx->gl_context == None)
|
||||
@ -208,6 +216,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
{
|
||||
g_critical ("Unable to create suitable GL context.");
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
return;
|
||||
@ -215,8 +224,8 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (GL, "glXMakeCurrent");
|
||||
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE(stage_glx));
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -276,6 +285,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
{
|
||||
g_critical ("Unable to create suitable GL context.");
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
return;
|
||||
@ -285,7 +295,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
/* below will call glxMakeCurrent */
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE(stage_glx));
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
|
||||
if (clutter_x11_untrap_x_errors ())
|
||||
{
|
||||
@ -295,14 +305,13 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
}
|
||||
|
||||
/* Make sure the viewport gets set up correctly */
|
||||
CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
return;
|
||||
|
||||
fail:
|
||||
|
||||
fail:
|
||||
/* For one reason or another we cant realize the stage.. */
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -312,8 +321,8 @@ snapshot_pixbuf_free (guchar *pixels,
|
||||
g_free (pixels);
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
clutter_stage_glx_draw_to_pixbuf (ClutterStage *stage,
|
||||
static GdkPixbuf *
|
||||
clutter_stage_glx_draw_to_pixbuf (ClutterStageWindow *stage_window,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
@ -326,9 +335,9 @@ clutter_stage_glx_draw_to_pixbuf (ClutterStage *stage,
|
||||
ClutterStageX11 *stage_x11;
|
||||
gboolean is_offscreen = FALSE;
|
||||
|
||||
stage_glx = CLUTTER_STAGE_GLX (stage);
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
actor = CLUTTER_ACTOR (stage);
|
||||
stage_glx = CLUTTER_STAGE_GLX (stage_window);
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
actor = CLUTTER_ACTOR (stage_window);
|
||||
|
||||
if (width < 0)
|
||||
width = clutter_actor_get_width (actor);
|
||||
@ -336,7 +345,7 @@ clutter_stage_glx_draw_to_pixbuf (ClutterStage *stage,
|
||||
if (height < 0)
|
||||
height = clutter_actor_get_height (actor);
|
||||
|
||||
g_object_get (stage, "offscreen", &is_offscreen, NULL);
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
|
||||
|
||||
if (G_UNLIKELY (is_offscreen))
|
||||
{
|
||||
@ -401,17 +410,22 @@ clutter_stage_glx_class_init (ClutterStageGLXClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = clutter_stage_glx_dispose;
|
||||
|
||||
actor_class->realize = clutter_stage_glx_realize;
|
||||
actor_class->unrealize = clutter_stage_glx_unrealize;
|
||||
stage_class->draw_to_pixbuf = clutter_stage_glx_draw_to_pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_glx_init (ClutterStageGLX *stage)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
||||
{
|
||||
iface->draw_to_pixbuf = clutter_stage_glx_draw_to_pixbuf;
|
||||
|
||||
/* the rest is inherited from ClutterStageX11 */
|
||||
}
|
||||
|
@ -331,6 +331,7 @@ event_translate (ClutterBackend *backend,
|
||||
ClutterBackendX11 *backend_x11;
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterStage *stage;
|
||||
ClutterStageWindow *impl;
|
||||
gboolean res;
|
||||
Window xwindow, stage_xwindow;
|
||||
|
||||
@ -375,7 +376,8 @@ event_translate (ClutterBackend *backend,
|
||||
if (stage == NULL)
|
||||
return FALSE;
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
||||
stage_xwindow = xwindow; /* clutter_x11_get_stage_window (stage); */
|
||||
|
||||
event->any.stage = stage;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "clutter-stage-x11.h"
|
||||
#include "clutter-x11.h"
|
||||
|
||||
#include "../clutter-stage-window.h"
|
||||
#include "../clutter-main.h"
|
||||
#include "../clutter-feature.h"
|
||||
#include "../clutter-color.h"
|
||||
@ -45,7 +46,13 @@
|
||||
|
||||
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
|
||||
|
||||
G_DEFINE_TYPE (ClutterStageX11, clutter_stage_x11, CLUTTER_TYPE_STAGE);
|
||||
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterStageX11,
|
||||
clutter_stage_x11,
|
||||
CLUTTER_TYPE_GROUP,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
||||
clutter_stage_window_iface_init));
|
||||
|
||||
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
|
||||
#define _NET_WM_STATE_ADD 1 /* add/set property */
|
||||
@ -84,7 +91,7 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11)
|
||||
{
|
||||
gboolean resize;
|
||||
|
||||
resize = clutter_stage_get_user_resizable (CLUTTER_STAGE (stage_x11));
|
||||
resize = clutter_stage_get_user_resizable (stage_x11->wrapper);
|
||||
|
||||
if (stage_x11->xwin != None && stage_x11->is_foreign_xwin == FALSE)
|
||||
{
|
||||
@ -117,7 +124,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_STAGE(actor));
|
||||
clutter_redraw (stage_x11->wrapper);
|
||||
|
||||
XSync (stage_x11->xdpy, FALSE);
|
||||
XMapWindow (stage_x11->xdpy, stage_x11->xwin);
|
||||
@ -208,7 +215,8 @@ clutter_stage_x11_request_coords (ClutterActor *self,
|
||||
clutter_actor_realize (self);
|
||||
}
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
CLUTTER_SET_PRIVATE_FLAGS (CLUTTER_ACTOR (stage_x11->wrapper),
|
||||
CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
|
||||
if (stage_x11->xwin != None
|
||||
@ -224,15 +232,18 @@ clutter_stage_x11_request_coords (ClutterActor *self,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_set_fullscreen (ClutterStage *stage,
|
||||
gboolean fullscreen)
|
||||
clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
|
||||
gboolean is_fullscreen)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
ClutterBackendX11 *backend_x11 = stage_x11->backend;
|
||||
|
||||
ClutterStage *stage = stage_x11->wrapper;
|
||||
static gboolean was_resizeable = FALSE;
|
||||
|
||||
if (fullscreen)
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
if (is_fullscreen)
|
||||
{
|
||||
if (stage_x11->xwin != None)
|
||||
{
|
||||
@ -311,19 +322,19 @@ clutter_stage_x11_set_fullscreen (ClutterStage *stage,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_set_cursor_visible (ClutterStage *stage,
|
||||
gboolean show_cursor)
|
||||
clutter_stage_x11_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||
gboolean cursor_visible)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
|
||||
if (stage_x11->xwin == None)
|
||||
return;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "setting cursor state ('%s') over stage window (%u)",
|
||||
show_cursor ? "visible" : "invisible",
|
||||
cursor_visible ? "visible" : "invisible",
|
||||
(unsigned int) stage_x11->xwin);
|
||||
|
||||
if (show_cursor)
|
||||
if (cursor_visible)
|
||||
{
|
||||
#if 0 /* HAVE_XFIXES - seems buggy/unreliable */
|
||||
XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||
@ -355,10 +366,10 @@ clutter_stage_x11_set_cursor_visible (ClutterStage *stage,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_set_title (ClutterStage *stage,
|
||||
clutter_stage_x11_set_title (ClutterStageWindow *stage_window,
|
||||
const gchar *title)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
ClutterBackendX11 *backend_x11 = stage_x11->backend;
|
||||
|
||||
if (stage_x11->xwin == None)
|
||||
@ -384,14 +395,20 @@ clutter_stage_x11_set_title (ClutterStage *stage,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_set_user_resize (ClutterStage *stage,
|
||||
gboolean value)
|
||||
clutter_stage_x11_set_user_resizable (ClutterStageWindow *stage_window,
|
||||
gboolean is_resizable)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
|
||||
clutter_stage_x11_fix_window_size (stage_x11);
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
clutter_stage_x11_get_wrapper (ClutterStageWindow *stage_window)
|
||||
{
|
||||
return CLUTTER_ACTOR (CLUTTER_STAGE_X11 (stage_window)->wrapper);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_dispose (GObject *gobject)
|
||||
{
|
||||
@ -408,7 +425,6 @@ clutter_stage_x11_class_init (ClutterStageX11Class *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = clutter_stage_x11_dispose;
|
||||
|
||||
@ -416,11 +432,6 @@ clutter_stage_x11_class_init (ClutterStageX11Class *klass)
|
||||
actor_class->hide = clutter_stage_x11_hide;
|
||||
actor_class->request_coords = clutter_stage_x11_request_coords;
|
||||
actor_class->query_coords = clutter_stage_x11_query_coords;
|
||||
|
||||
stage_class->set_fullscreen = clutter_stage_x11_set_fullscreen;
|
||||
stage_class->set_cursor_visible = clutter_stage_x11_set_cursor_visible;
|
||||
stage_class->set_title = clutter_stage_x11_set_title;
|
||||
stage_class->set_user_resize = clutter_stage_x11_set_user_resize;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -439,7 +450,22 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
|
||||
stage->fullscreen_on_map = FALSE;
|
||||
stage->handling_configure = FALSE;
|
||||
|
||||
stage->wrapper = NULL;
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_IS_TOPLEVEL);
|
||||
#if 0
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
||||
{
|
||||
iface->get_wrapper = clutter_stage_x11_get_wrapper;
|
||||
iface->set_title = clutter_stage_x11_set_title;
|
||||
iface->set_fullscreen = clutter_stage_x11_set_fullscreen;
|
||||
iface->set_cursor_visible = clutter_stage_x11_set_cursor_visible;
|
||||
iface->set_user_resizable = clutter_stage_x11_set_user_resizable;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -455,9 +481,14 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
|
||||
Window
|
||||
clutter_x11_get_stage_window (ClutterStage *stage)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE_X11 (stage), None);
|
||||
ClutterStageWindow *impl;
|
||||
|
||||
return CLUTTER_STAGE_X11 (stage)->xwin;
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), None);
|
||||
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
g_assert (CLUTTER_IS_STAGE_X11 (impl));
|
||||
|
||||
return CLUTTER_STAGE_X11 (impl)->xwin;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -470,7 +501,7 @@ clutter_x11_get_stage_window (ClutterStage *stage)
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
ClutterStage*
|
||||
ClutterStage *
|
||||
clutter_x11_get_stage_from_window (Window win)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
@ -484,10 +515,14 @@ clutter_x11_get_stage_from_window (Window win)
|
||||
/* 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);
|
||||
ClutterStage *stage = l->data;
|
||||
ClutterStageWindow *impl;
|
||||
|
||||
if (stage_x11->xwin == win)
|
||||
return CLUTTER_STAGE(stage_x11);
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
g_assert (CLUTTER_IS_STAGE_X11 (impl));
|
||||
|
||||
if (CLUTTER_STAGE_X11 (impl)->xwin == win)
|
||||
return stage;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -506,9 +541,14 @@ clutter_x11_get_stage_from_window (Window win)
|
||||
XVisualInfo *
|
||||
clutter_x11_get_stage_visual (ClutterStage *stage)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE_X11 (stage), NULL);
|
||||
ClutterStageWindow *impl;
|
||||
|
||||
return CLUTTER_STAGE_X11 (stage)->xvisinfo;
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
|
||||
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
g_assert (CLUTTER_IS_STAGE_X11 (impl));
|
||||
|
||||
return CLUTTER_STAGE_X11 (impl)->xvisinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -527,6 +567,7 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
|
||||
Window xwindow)
|
||||
{
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterStageWindow *impl;
|
||||
ClutterActor *actor;
|
||||
gint x, y;
|
||||
guint width, height, border, depth;
|
||||
@ -534,11 +575,12 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
|
||||
Status status;
|
||||
ClutterGeometry geom;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE_X11 (stage), FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
|
||||
g_return_val_if_fail (xwindow != None, FALSE);
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
actor = CLUTTER_ACTOR (stage);
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
stage_x11 = CLUTTER_STAGE_X11 (impl);
|
||||
actor = CLUTTER_ACTOR (impl);
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
@ -577,19 +619,27 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
|
||||
void
|
||||
clutter_stage_x11_map (ClutterStageX11 *stage_x11)
|
||||
{
|
||||
/* set the mapped flag on the implementation */
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11, CLUTTER_ACTOR_MAPPED);
|
||||
|
||||
if (stage_x11->fullscreen_on_map)
|
||||
clutter_stage_fullscreen (CLUTTER_STAGE (stage_x11));
|
||||
else
|
||||
clutter_stage_unfullscreen (CLUTTER_STAGE (stage_x11));
|
||||
/* and on the wrapper itself */
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_MAPPED);
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage_x11));
|
||||
if (stage_x11->fullscreen_on_map)
|
||||
clutter_stage_fullscreen (CLUTTER_STAGE (stage_x11->wrapper));
|
||||
else
|
||||
clutter_stage_unfullscreen (CLUTTER_STAGE (stage_x11->wrapper));
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage_x11->wrapper));
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_x11_unmap (ClutterStageX11 *stage_x11)
|
||||
{
|
||||
/* like above, unset the MAPPED stage on both the implementation and
|
||||
* the wrapper
|
||||
*/
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11, CLUTTER_ACTOR_MAPPED);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_MAPPED);
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#ifndef __CLUTTER_STAGE_X11_H__
|
||||
#define __CLUTTER_STAGE_X11_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-group.h>
|
||||
#include <clutter/clutter-stage.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
@ -43,7 +43,7 @@ typedef struct _ClutterStageX11Class ClutterStageX11Class;
|
||||
|
||||
struct _ClutterStageX11
|
||||
{
|
||||
ClutterStage parent_instance;
|
||||
ClutterGroup parent_instance;
|
||||
|
||||
guint is_foreign_xwin : 1;
|
||||
guint fullscreen_on_map : 1;
|
||||
@ -60,11 +60,13 @@ struct _ClutterStageX11
|
||||
|
||||
ClutterBackendX11 *backend;
|
||||
ClutterStageState state;
|
||||
|
||||
ClutterStage *wrapper;
|
||||
};
|
||||
|
||||
struct _ClutterStageX11Class
|
||||
{
|
||||
ClutterStageClass parent_class;
|
||||
ClutterGroupClass parent_class;
|
||||
};
|
||||
|
||||
GType clutter_stage_x11_get_type (void) G_GNUC_CONST;
|
||||
@ -72,7 +74,6 @@ GType clutter_stage_x11_get_type (void) G_GNUC_CONST;
|
||||
/* Private to subclasses */
|
||||
void clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11);
|
||||
void clutter_stage_x11_set_wm_protocols (ClutterStageX11 *stage_x11);
|
||||
|
||||
void clutter_stage_x11_map (ClutterStageX11 *stage_x11);
|
||||
void clutter_stage_x11_unmap (ClutterStageX11 *stage_x11);
|
||||
|
||||
|
@ -26,7 +26,7 @@ on_button_press (ClutterActor *actor,
|
||||
ClutterAlpha *alpha;
|
||||
ClutterBehaviour *r_behave;
|
||||
|
||||
new_stage = clutter_stage_create_new ();
|
||||
new_stage = clutter_stage_new ();
|
||||
|
||||
/* FIXME: below should really be automatic */
|
||||
/* clutter_stage_ensure_cogl_context (CLUTTER_STAGE(new_stage)); */
|
||||
|
Loading…
Reference in New Issue
Block a user