mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
2007-08-24 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-actor.c: * clutter/clutter-event.h: * clutter/clutter-main.c: * clutter/clutter-stage.c: * clutter/clutter-stage.h: * clutter/glx/clutter-backend-glx.c: * clutter/glx/clutter-backend-glx.h: * clutter/glx/clutter-event-glx.c: * clutter/glx/clutter-stage-glx.c: * clutter/glx/clutter-stage-glx.h: Add initial support for stage state events. Fix fullscreening for an already mapped stage. * tests/test-events.c: Print out info from the above. Blue button now toggles fullscreen. * clutter/clutter-effect.c: * clutter/clutter-effect.h: Add a setting for templates to ref or clone underlying timelines. (As to improve sync issues like those in foofone) * tests/test-timeline.c: Also add completed signals. * clutter/cogl/gles/cogl.c: (cogl_texture_image_2d): * configure.ac: Forward port from stable branch. RGB Image fixes gles and check for lower case libgles_cm.
This commit is contained in:
parent
e0f609e8aa
commit
1ceaf04ac7
33
ChangeLog
33
ChangeLog
@ -1,3 +1,36 @@
|
|||||||
|
2007-08-24 Matthew Allum <mallum@openedhand.com>
|
||||||
|
|
||||||
|
* clutter/clutter-actor.c:
|
||||||
|
* clutter/clutter-event.h:
|
||||||
|
* clutter/clutter-main.c:
|
||||||
|
* clutter/clutter-stage.c:
|
||||||
|
* clutter/clutter-stage.h:
|
||||||
|
* clutter/glx/clutter-backend-glx.c:
|
||||||
|
* clutter/glx/clutter-backend-glx.h:
|
||||||
|
* clutter/glx/clutter-event-glx.c:
|
||||||
|
* clutter/glx/clutter-stage-glx.c:
|
||||||
|
* clutter/glx/clutter-stage-glx.h:
|
||||||
|
Add initial support for stage state events.
|
||||||
|
Fix fullscreening for an already mapped stage.
|
||||||
|
|
||||||
|
* tests/test-events.c:
|
||||||
|
Print out info from the above. Blue button now toggles
|
||||||
|
fullscreen.
|
||||||
|
|
||||||
|
* clutter/clutter-effect.c:
|
||||||
|
* clutter/clutter-effect.h:
|
||||||
|
Add a setting for templates to ref or clone underlying
|
||||||
|
timelines. (As to improve sync issues like those in foofone)
|
||||||
|
|
||||||
|
* tests/test-timeline.c:
|
||||||
|
Also add completed signals.
|
||||||
|
|
||||||
|
* clutter/cogl/gles/cogl.c: (cogl_texture_image_2d):
|
||||||
|
* configure.ac:
|
||||||
|
Forward port from stable branch. RGB Image fixes gles
|
||||||
|
and check for lower case libgles_cm.
|
||||||
|
|
||||||
|
|
||||||
2007-08-24 Tomas Frydrych <tf@openedhand.com>
|
2007-08-24 Tomas Frydrych <tf@openedhand.com>
|
||||||
|
|
||||||
* clutter/clutter-actor.c:
|
* clutter/clutter-actor.c:
|
||||||
|
@ -2861,15 +2861,10 @@ clutter_actor_event (ClutterActor *actor,
|
|||||||
signal_num = MOTION_EVENT;
|
signal_num = MOTION_EVENT;
|
||||||
break;
|
break;
|
||||||
case CLUTTER_DELETE:
|
case CLUTTER_DELETE:
|
||||||
signal_num = -1;
|
|
||||||
break;
|
|
||||||
case CLUTTER_DESTROY_NOTIFY:
|
case CLUTTER_DESTROY_NOTIFY:
|
||||||
signal_num = -1;
|
|
||||||
break;
|
|
||||||
case CLUTTER_CLIENT_MESSAGE:
|
case CLUTTER_CLIENT_MESSAGE:
|
||||||
signal_num = -1;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
|
signal_num = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ G_DEFINE_TYPE (ClutterEffectTemplate, clutter_effect_template, G_TYPE_OBJECT);
|
|||||||
struct _ClutterEffectTemplatePrivate
|
struct _ClutterEffectTemplatePrivate
|
||||||
{
|
{
|
||||||
ClutterTimeline *timeline;
|
ClutterTimeline *timeline;
|
||||||
|
gboolean do_clone;
|
||||||
|
|
||||||
ClutterAlphaFunc alpha_func;
|
ClutterAlphaFunc alpha_func;
|
||||||
gpointer alpha_data;
|
gpointer alpha_data;
|
||||||
@ -94,6 +95,7 @@ enum
|
|||||||
|
|
||||||
PROP_ALPHA_FUNC,
|
PROP_ALPHA_FUNC,
|
||||||
PROP_TIMELINE,
|
PROP_TIMELINE,
|
||||||
|
PROP_DO_CLONE
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -152,6 +154,9 @@ clutter_effect_template_set_property (GObject *object,
|
|||||||
case PROP_TIMELINE:
|
case PROP_TIMELINE:
|
||||||
priv->timeline = g_value_get_object (value);
|
priv->timeline = g_value_get_object (value);
|
||||||
g_object_ref(priv->timeline);
|
g_object_ref(priv->timeline);
|
||||||
|
case PROP_DO_CLONE:
|
||||||
|
clutter_effect_template_set_timeline_clone (template,
|
||||||
|
g_value_get_boolean (value));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
@ -179,6 +184,9 @@ clutter_effect_template_get_property (GObject *object,
|
|||||||
case PROP_TIMELINE:
|
case PROP_TIMELINE:
|
||||||
g_value_set_object (value, priv->timeline);
|
g_value_set_object (value, priv->timeline);
|
||||||
break;
|
break;
|
||||||
|
case PROP_DO_CLONE:
|
||||||
|
g_value_set_boolean (value, priv->do_clone);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
@ -228,12 +236,31 @@ clutter_effect_template_class_init (ClutterEffectTemplateClass *klass)
|
|||||||
CLUTTER_TYPE_TIMELINE,
|
CLUTTER_TYPE_TIMELINE,
|
||||||
G_PARAM_CONSTRUCT_ONLY |
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
CLUTTER_PARAM_READWRITE));
|
CLUTTER_PARAM_READWRITE));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterEffectTemplate:clone:
|
||||||
|
*
|
||||||
|
* Controls if effects should clone or reference the templated timeline
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
g_object_class_install_property
|
||||||
|
(object_class,
|
||||||
|
PROP_DO_CLONE,
|
||||||
|
g_param_spec_boolean ("clone",
|
||||||
|
"Clone",
|
||||||
|
"controls if effects should clone or reference the templated timeline",
|
||||||
|
TRUE,
|
||||||
|
G_PARAM_CONSTRUCT |
|
||||||
|
CLUTTER_PARAM_READWRITE));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_effect_template_init (ClutterEffectTemplate *self)
|
clutter_effect_template_init (ClutterEffectTemplate *self)
|
||||||
{
|
{
|
||||||
self->priv = EFFECT_TEMPLATE_PRIVATE (self);
|
self->priv = EFFECT_TEMPLATE_PRIVATE (self);
|
||||||
|
self->priv->do_clone = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -257,6 +284,40 @@ clutter_effect_template_set_alpha_func (ClutterEffectTemplate *self,
|
|||||||
priv->alpha_func = alpha_func;
|
priv->alpha_func = alpha_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_effect_template_set_timeline_clone:
|
||||||
|
* @template_: A #ClutterEffectTemplate
|
||||||
|
* @setting: A boolean indicating if effects should clone the timeline.
|
||||||
|
*
|
||||||
|
* Sets if effects using this template should make a copy of the
|
||||||
|
* templates timeline (default) or reference the effects timeline.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_effect_template_set_timeline_clone (ClutterEffectTemplate *template_,
|
||||||
|
gboolean setting)
|
||||||
|
{
|
||||||
|
template_->priv->do_clone = setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_effect_template_get_timeline_clone:
|
||||||
|
* @template: A #ClutterEffectTemplate
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Return value: TRUE if the templates timeline is to be cloned.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
clutter_effect_template_get_timeline_clone (ClutterEffectTemplate *template_)
|
||||||
|
{
|
||||||
|
return template_->priv->do_clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_effect_template_new:
|
* clutter_effect_template_new:
|
||||||
* @timeline: A #ClutterTimeline for the template (will be cloned)
|
* @timeline: A #ClutterTimeline for the template (will be cloned)
|
||||||
@ -276,7 +337,7 @@ clutter_effect_template_set_alpha_func (ClutterEffectTemplate *self,
|
|||||||
*
|
*
|
||||||
* Since: 0.4
|
* Since: 0.4
|
||||||
*/
|
*/
|
||||||
ClutterEffectTemplate *
|
ClutterEffectTemplate*
|
||||||
clutter_effect_template_new (ClutterTimeline *timeline,
|
clutter_effect_template_new (ClutterTimeline *timeline,
|
||||||
ClutterAlphaFunc alpha_func)
|
ClutterAlphaFunc alpha_func)
|
||||||
{
|
{
|
||||||
@ -368,7 +429,15 @@ clutter_effect_closure_new (ClutterEffectTemplate *template,
|
|||||||
|
|
||||||
c->template = template;
|
c->template = template;
|
||||||
c->actor = actor;
|
c->actor = actor;
|
||||||
c->timeline = clutter_timeline_clone (priv->timeline);
|
|
||||||
|
if (clutter_effect_template_get_timeline_clone (template))
|
||||||
|
c->timeline = clutter_timeline_clone (priv->timeline);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->timeline = priv->timeline;
|
||||||
|
g_object_ref (priv->timeline);
|
||||||
|
}
|
||||||
|
|
||||||
c->alpha = clutter_alpha_new_full (c->timeline,
|
c->alpha = clutter_alpha_new_full (c->timeline,
|
||||||
priv->alpha_func,
|
priv->alpha_func,
|
||||||
priv->alpha_data,
|
priv->alpha_data,
|
||||||
|
@ -101,6 +101,11 @@ ClutterEffectTemplate *clutter_effect_template_new_full (ClutterTimeline *timel
|
|||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GDestroyNotify notify);
|
GDestroyNotify notify);
|
||||||
|
|
||||||
|
void clutter_effect_template_set_timeline_clone (ClutterEffectTemplate *template_,
|
||||||
|
gboolean setting);
|
||||||
|
gboolean clutter_effect_template_get_timeline_clone (ClutterEffectTemplate *template_);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clutter effects
|
* Clutter effects
|
||||||
*/
|
*/
|
||||||
|
@ -83,8 +83,7 @@ typedef enum
|
|||||||
CLUTTER_STAGE_STATE_OFFSCREEN = (1<<2),
|
CLUTTER_STAGE_STATE_OFFSCREEN = (1<<2),
|
||||||
CLUTTER_STAGE_STATE_POINTER_ENTER = (1<<3),
|
CLUTTER_STAGE_STATE_POINTER_ENTER = (1<<3),
|
||||||
CLUTTER_STAGE_STATE_POINTER_LEAVE = (1<<4),
|
CLUTTER_STAGE_STATE_POINTER_LEAVE = (1<<4),
|
||||||
CLUTTER_STAGE_STATE_FOCUS_ACTIVATE = (1<<5),
|
CLUTTER_STAGE_STATE_ACTIVATED = (1<<5),
|
||||||
CLUTTER_STAGE_STATE_FOCUS_DEACTIVATE = (1<<6),
|
|
||||||
} ClutterStageState;
|
} ClutterStageState;
|
||||||
|
|
||||||
typedef union _ClutterEvent ClutterEvent;
|
typedef union _ClutterEvent ClutterEvent;
|
||||||
|
@ -315,7 +315,8 @@ clutter_do_event (ClutterEvent *event)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CLUTTER_STAGE_STATE:
|
case CLUTTER_STAGE_STATE:
|
||||||
/* FIXME: fullscreen / focus / mouse - forward to stage */
|
/* fullscreen / focus - forward to stage */
|
||||||
|
clutter_stage_event (CLUTTER_STAGE(stage), event);
|
||||||
break;
|
break;
|
||||||
case CLUTTER_CLIENT_MESSAGE:
|
case CLUTTER_CLIENT_MESSAGE:
|
||||||
break;
|
break;
|
||||||
|
@ -82,9 +82,10 @@ enum
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
STAGE_STATE_EVENT,
|
FULLSCREEN,
|
||||||
ACTIVATE_STAGE,
|
UNFULLSCREEN,
|
||||||
DEACTIVATE_STAGE,
|
ACTIVATE,
|
||||||
|
DEACTIVATE,
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -295,6 +296,78 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
|||||||
"Stage Title",
|
"Stage Title",
|
||||||
NULL,
|
NULL,
|
||||||
CLUTTER_PARAM_READWRITE));
|
CLUTTER_PARAM_READWRITE));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterStage::fullscreen
|
||||||
|
* @stage: the stage which was fullscreened
|
||||||
|
*
|
||||||
|
* The ::fullscreen signal is emitted when the stage is made fullscreen.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
stage_signals[FULLSCREEN] =
|
||||||
|
g_signal_new ("fullscreen",
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (ClutterStageClass, fullscreen),
|
||||||
|
NULL, NULL,
|
||||||
|
clutter_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterStage::unfullscreen
|
||||||
|
* @stage: the stage which has left a fullscreen state.
|
||||||
|
*
|
||||||
|
* The ::unfullscreen signal is emitted when the stage leaves a fullscreen
|
||||||
|
* state.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
stage_signals[UNFULLSCREEN] =
|
||||||
|
g_signal_new ("unfullscreen",
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (ClutterStageClass, unfullscreen),
|
||||||
|
NULL, NULL,
|
||||||
|
clutter_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterStage::activate
|
||||||
|
* @stage: the stage which was activated
|
||||||
|
*
|
||||||
|
* The ::activate signal is emitted when the stage recieves key focus
|
||||||
|
* from the underlying window system.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
stage_signals[ACTIVATE] =
|
||||||
|
g_signal_new ("activate",
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (ClutterStageClass, activate),
|
||||||
|
NULL, NULL,
|
||||||
|
clutter_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterStage::deactivate
|
||||||
|
* @stage: the stage which was deactivated
|
||||||
|
*
|
||||||
|
* The ::activate signal is emitted when the stage loses key focus
|
||||||
|
* from the underlying window system.
|
||||||
|
*
|
||||||
|
* Since: 0.6
|
||||||
|
*/
|
||||||
|
stage_signals[DEACTIVATE] =
|
||||||
|
g_signal_new ("deactivate",
|
||||||
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
G_STRUCT_OFFSET (ClutterStageClass, deactivate),
|
||||||
|
NULL, NULL,
|
||||||
|
clutter_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
g_type_class_add_private (gobject_class, sizeof (ClutterStagePrivate));
|
g_type_class_add_private (gobject_class, sizeof (ClutterStagePrivate));
|
||||||
}
|
}
|
||||||
@ -750,7 +823,30 @@ clutter_stage_event (ClutterStage *stage,
|
|||||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
|
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
|
||||||
g_return_val_if_fail (event != NULL, FALSE);
|
g_return_val_if_fail (event != NULL, FALSE);
|
||||||
|
|
||||||
/* FIXME: Handle StageState Changes and Delete events */
|
if (event->type == CLUTTER_DELETE)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (event->type != CLUTTER_STAGE_STATE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* emit raw event */
|
||||||
|
clutter_actor_event (CLUTTER_ACTOR(stage), event);
|
||||||
|
|
||||||
|
if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_FULLSCREEN)
|
||||||
|
{
|
||||||
|
if (event->stage_state.new_state & CLUTTER_STAGE_STATE_FULLSCREEN)
|
||||||
|
g_signal_emit (stage, stage_signals[FULLSCREEN], 0);
|
||||||
|
else
|
||||||
|
g_signal_emit (stage, stage_signals[UNFULLSCREEN], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_ACTIVATED)
|
||||||
|
{
|
||||||
|
if (event->stage_state.new_state & CLUTTER_STAGE_STATE_ACTIVATED)
|
||||||
|
g_signal_emit (stage, stage_signals[ACTIVATE], 0);
|
||||||
|
else
|
||||||
|
g_signal_emit (stage, stage_signals[DEACTIVATE], 0);
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -99,8 +99,10 @@ struct _ClutterStageClass
|
|||||||
gboolean value);
|
gboolean value);
|
||||||
|
|
||||||
/* events */
|
/* events */
|
||||||
void (* stage_state_event) (ClutterStage *stage,
|
void (* fullscreen) (ClutterStage *stage);
|
||||||
ClutterStageStateEvent *event);
|
void (* unfullscreen) (ClutterStage *stage);
|
||||||
|
void (* activate) (ClutterStage *stage);
|
||||||
|
void (* deactivate) (ClutterStage *stage);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
/* padding for future expansion */
|
/* padding for future expansion */
|
||||||
|
@ -374,11 +374,17 @@ cogl_texture_image_2d (COGLenum target,
|
|||||||
const guchar* pixels)
|
const guchar* pixels)
|
||||||
{
|
{
|
||||||
GE( glTexImage2D (target,
|
GE( glTexImage2D (target,
|
||||||
0, /* No mipmap support as yet */
|
0,
|
||||||
internal_format,
|
format, /* HACK: For gles we set the internal_format equal
|
||||||
|
* to the pixel format. This is for RGB data (i.e
|
||||||
|
* jpgs) which seem to need a matching internal
|
||||||
|
* format rather than RGBA (which is used by GL)
|
||||||
|
*.
|
||||||
|
* This fix isn't ideal..
|
||||||
|
*/
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
0, /* 0 pixel border */
|
0,
|
||||||
format,
|
format,
|
||||||
type,
|
type,
|
||||||
pixels) );
|
pixels) );
|
||||||
|
@ -210,6 +210,11 @@ clutter_backend_glx_post_parse (ClutterBackend *backend,
|
|||||||
|
|
||||||
if (clutter_synchronise)
|
if (clutter_synchronise)
|
||||||
XSynchronize (backend_glx->xdpy, True);
|
XSynchronize (backend_glx->xdpy, True);
|
||||||
|
|
||||||
|
backend_glx->atom_WM_STATE
|
||||||
|
= XInternAtom (backend_glx->xdpy, "_NET_WM_STATE", False);
|
||||||
|
backend_glx->atom_WM_STATE_FULLSCREEN
|
||||||
|
= XInternAtom (backend_glx->xdpy, "_NET_WM_STATE_FULLSCREEN", False);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (clutter_display_name);
|
g_free (clutter_display_name);
|
||||||
|
@ -89,6 +89,10 @@ struct _ClutterBackendGLX
|
|||||||
SwapIntervalProc swap_interval;
|
SwapIntervalProc swap_interval;
|
||||||
gint dri_fd;
|
gint dri_fd;
|
||||||
ClutterGLXVBlankType vblank_type;
|
ClutterGLXVBlankType vblank_type;
|
||||||
|
|
||||||
|
/* props */
|
||||||
|
Atom atom_WM_STATE;
|
||||||
|
Atom atom_WM_STATE_FULLSCREEN;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendGLXClass
|
struct _ClutterBackendGLXClass
|
||||||
|
@ -355,13 +355,15 @@ event_translate (ClutterBackend *backend,
|
|||||||
XEvent *xevent)
|
XEvent *xevent)
|
||||||
{
|
{
|
||||||
ClutterBackendGLX *backend_glx;
|
ClutterBackendGLX *backend_glx;
|
||||||
ClutterStage *stage;
|
ClutterStageGLX *stage_glx;
|
||||||
gboolean res;
|
ClutterStage *stage;
|
||||||
Window xwindow, stage_xwindow;
|
gboolean res;
|
||||||
|
Window xwindow, stage_xwindow;
|
||||||
|
|
||||||
backend_glx = CLUTTER_BACKEND_GLX (backend);
|
backend_glx = CLUTTER_BACKEND_GLX (backend);
|
||||||
stage = CLUTTER_STAGE (_clutter_backend_get_stage (backend));
|
stage = CLUTTER_STAGE (_clutter_backend_get_stage (backend));
|
||||||
stage_xwindow = clutter_glx_get_stage_window (stage);
|
stage_glx = CLUTTER_STAGE_GLX (stage);
|
||||||
|
stage_xwindow = clutter_glx_get_stage_window (stage);
|
||||||
|
|
||||||
xwindow = xevent->xany.window;
|
xwindow = xevent->xany.window;
|
||||||
if (xwindow == None)
|
if (xwindow == None)
|
||||||
@ -397,6 +399,99 @@ event_translate (ClutterBackend *backend,
|
|||||||
|
|
||||||
switch (xevent->type)
|
switch (xevent->type)
|
||||||
{
|
{
|
||||||
|
case ConfigureNotify:
|
||||||
|
if (xevent->xconfigure.width
|
||||||
|
!= clutter_actor_get_width (CLUTTER_ACTOR (stage))
|
||||||
|
||
|
||||||
|
xevent->xconfigure.height
|
||||||
|
!= clutter_actor_get_height (CLUTTER_ACTOR (stage)))
|
||||||
|
clutter_actor_set_size (CLUTTER_ACTOR (stage),
|
||||||
|
xevent->xconfigure.width,
|
||||||
|
xevent->xconfigure.height);
|
||||||
|
res = FALSE;
|
||||||
|
break;
|
||||||
|
case PropertyNotify:
|
||||||
|
{
|
||||||
|
if (xevent->xproperty.atom == backend_glx->atom_WM_STATE)
|
||||||
|
{
|
||||||
|
Atom type;
|
||||||
|
gint format;
|
||||||
|
gulong nitems, bytes_after;
|
||||||
|
guchar *data = NULL;
|
||||||
|
Atom *atoms = NULL;
|
||||||
|
gulong i;
|
||||||
|
gboolean fullscreen_set = FALSE;
|
||||||
|
|
||||||
|
clutter_glx_trap_x_errors ();
|
||||||
|
XGetWindowProperty (backend_glx->xdpy,
|
||||||
|
stage_xwindow,
|
||||||
|
backend_glx->atom_WM_STATE,
|
||||||
|
0, G_MAXLONG,
|
||||||
|
False, XA_ATOM,
|
||||||
|
&type, &format, &nitems,
|
||||||
|
&bytes_after, &data);
|
||||||
|
clutter_glx_untrap_x_errors ();
|
||||||
|
|
||||||
|
if (type != None && data != NULL)
|
||||||
|
{
|
||||||
|
atoms = (Atom *)data;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < nitems)
|
||||||
|
{
|
||||||
|
if (atoms[i] == backend_glx->atom_WM_STATE_FULLSCREEN)
|
||||||
|
fullscreen_set = TRUE;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullscreen_set
|
||||||
|
!= !!(stage_glx->state & CLUTTER_STAGE_STATE_FULLSCREEN))
|
||||||
|
{
|
||||||
|
if (fullscreen_set)
|
||||||
|
stage_glx->state |= CLUTTER_STAGE_STATE_FULLSCREEN;
|
||||||
|
else
|
||||||
|
stage_glx->state &= ~CLUTTER_STAGE_STATE_FULLSCREEN;
|
||||||
|
|
||||||
|
event->type = CLUTTER_STAGE_STATE;
|
||||||
|
event->stage_state.changed_mask
|
||||||
|
= CLUTTER_STAGE_STATE_FULLSCREEN;
|
||||||
|
event->stage_state.new_state = stage_glx->state;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res = FALSE;
|
||||||
|
|
||||||
|
XFree (data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res = FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FocusIn:
|
||||||
|
if (!(stage_glx->state & CLUTTER_STAGE_STATE_ACTIVATED))
|
||||||
|
{
|
||||||
|
/* TODO: check xevent->xfocus.detail ? */
|
||||||
|
stage_glx->state |= CLUTTER_STAGE_STATE_ACTIVATED;
|
||||||
|
|
||||||
|
event->type = CLUTTER_STAGE_STATE;
|
||||||
|
event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
|
||||||
|
event->stage_state.new_state = stage_glx->state;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res = FALSE;
|
||||||
|
break;
|
||||||
|
case FocusOut:
|
||||||
|
if (stage_glx->state & CLUTTER_STAGE_STATE_ACTIVATED)
|
||||||
|
{
|
||||||
|
stage_glx->state &= ~CLUTTER_STAGE_STATE_ACTIVATED;
|
||||||
|
|
||||||
|
event->type = CLUTTER_STAGE_STATE;
|
||||||
|
event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED;
|
||||||
|
event->stage_state.new_state = stage_glx->state;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
res = FALSE;
|
||||||
|
break;
|
||||||
case Expose:
|
case Expose:
|
||||||
{
|
{
|
||||||
XEvent foo_xev;
|
XEvent foo_xev;
|
||||||
|
@ -50,6 +50,38 @@
|
|||||||
|
|
||||||
G_DEFINE_TYPE (ClutterStageGLX, clutter_stage_glx, CLUTTER_TYPE_STAGE);
|
G_DEFINE_TYPE (ClutterStageGLX, clutter_stage_glx, CLUTTER_TYPE_STAGE);
|
||||||
|
|
||||||
|
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
|
||||||
|
#define _NET_WM_STATE_ADD 1 /* add/set property */
|
||||||
|
#define _NET_WM_STATE_TOGGLE 2 /* toggle property */
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_wmspec_change_state (ClutterBackendGLX *backend_glx,
|
||||||
|
Window window,
|
||||||
|
Atom state,
|
||||||
|
gboolean add)
|
||||||
|
{
|
||||||
|
XClientMessageEvent xclient;
|
||||||
|
|
||||||
|
memset (&xclient, 0, sizeof (xclient));
|
||||||
|
|
||||||
|
xclient.type = ClientMessage;
|
||||||
|
xclient.window = window;
|
||||||
|
xclient.message_type = backend_glx->atom_WM_STATE;
|
||||||
|
xclient.format = 32;
|
||||||
|
|
||||||
|
xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
||||||
|
xclient.data.l[1] = state;
|
||||||
|
xclient.data.l[2] = 0;
|
||||||
|
xclient.data.l[3] = 0;
|
||||||
|
xclient.data.l[4] = 0;
|
||||||
|
|
||||||
|
XSendEvent (backend_glx->xdpy,
|
||||||
|
DefaultRootWindow(backend_glx->xdpy),
|
||||||
|
False,
|
||||||
|
SubstructureRedirectMask|SubstructureNotifyMask,
|
||||||
|
(XEvent *)&xclient);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fix_window_size (ClutterStageGLX *stage_glx)
|
fix_window_size (ClutterStageGLX *stage_glx)
|
||||||
{
|
{
|
||||||
@ -83,6 +115,9 @@ clutter_stage_glx_show (ClutterActor *actor)
|
|||||||
{
|
{
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
||||||
|
|
||||||
|
/* Chain up to set mapped flags */
|
||||||
|
CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->show(actor);
|
||||||
|
|
||||||
if (stage_glx->xwin)
|
if (stage_glx->xwin)
|
||||||
{
|
{
|
||||||
/* Fire off a redraw to avoid flicker on first map.
|
/* Fire off a redraw to avoid flicker on first map.
|
||||||
@ -236,6 +271,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
|||||||
CLUTTER_NOTE (MISC, "XSelectInput");
|
CLUTTER_NOTE (MISC, "XSelectInput");
|
||||||
XSelectInput (stage_glx->xdpy, stage_glx->xwin,
|
XSelectInput (stage_glx->xdpy, stage_glx->xwin,
|
||||||
StructureNotifyMask |
|
StructureNotifyMask |
|
||||||
|
FocusChangeMask |
|
||||||
ExposureMask |
|
ExposureMask |
|
||||||
/* FIXME: we may want to eplicity enable MotionMask */
|
/* FIXME: we may want to eplicity enable MotionMask */
|
||||||
PointerMotionMask |
|
PointerMotionMask |
|
||||||
@ -434,33 +470,76 @@ clutter_stage_glx_set_fullscreen (ClutterStage *stage,
|
|||||||
gboolean fullscreen)
|
gboolean fullscreen)
|
||||||
{
|
{
|
||||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage);
|
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage);
|
||||||
Atom atom_WM_STATE, atom_WM_STATE_FULLSCREEN;
|
ClutterBackendGLX *backend_glx = stage_glx->backend;
|
||||||
|
|
||||||
atom_WM_STATE = XInternAtom (stage_glx->xdpy, "_NET_WM_STATE", False);
|
static gboolean was_resizeable = FALSE;
|
||||||
atom_WM_STATE_FULLSCREEN = XInternAtom (stage_glx->xdpy,
|
|
||||||
"_NET_WM_STATE_FULLSCREEN",
|
|
||||||
False);
|
|
||||||
|
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
{
|
{
|
||||||
gint width, height;
|
|
||||||
|
|
||||||
width = DisplayWidth (stage_glx->xdpy, stage_glx->xscreen);
|
|
||||||
height = DisplayHeight (stage_glx->xdpy, stage_glx->xscreen);
|
|
||||||
|
|
||||||
clutter_actor_set_size (CLUTTER_ACTOR (stage_glx), width, height);
|
|
||||||
|
|
||||||
if (stage_glx->xwin != None)
|
if (stage_glx->xwin != None)
|
||||||
XChangeProperty (stage_glx->xdpy,
|
{
|
||||||
stage_glx->xwin,
|
if (!CLUTTER_ACTOR_IS_MAPPED(CLUTTER_ACTOR (stage_glx)))
|
||||||
atom_WM_STATE, XA_ATOM, 32,
|
{
|
||||||
PropModeReplace,
|
gint width, height;
|
||||||
(unsigned char *) &atom_WM_STATE_FULLSCREEN, 1);
|
|
||||||
|
width = DisplayWidth (stage_glx->xdpy, stage_glx->xscreen);
|
||||||
|
height = DisplayHeight (stage_glx->xdpy, stage_glx->xscreen);
|
||||||
|
|
||||||
|
clutter_actor_set_size (CLUTTER_ACTOR (stage_glx),
|
||||||
|
width, height);
|
||||||
|
/* FIXME: This wont work if we support more states */
|
||||||
|
XChangeProperty
|
||||||
|
(stage_glx->xdpy,
|
||||||
|
stage_glx->xwin,
|
||||||
|
backend_glx->atom_WM_STATE, XA_ATOM, 32,
|
||||||
|
PropModeReplace,
|
||||||
|
(unsigned char *)&backend_glx->atom_WM_STATE_FULLSCREEN,
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We need to set window user resize-able for metacity at
|
||||||
|
* at least to allow the window to fullscreen *sigh*
|
||||||
|
*/
|
||||||
|
if (clutter_stage_get_user_resizable (stage) == TRUE)
|
||||||
|
was_resizeable = TRUE;
|
||||||
|
else
|
||||||
|
clutter_stage_set_user_resizable (stage, TRUE);
|
||||||
|
|
||||||
|
send_wmspec_change_state(backend_glx,
|
||||||
|
stage_glx->xwin,
|
||||||
|
backend_glx->atom_WM_STATE_FULLSCREEN,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (stage_glx->xwin != None)
|
if (stage_glx->xwin != None)
|
||||||
XDeleteProperty (stage_glx->xdpy, stage_glx->xwin, atom_WM_STATE);
|
{
|
||||||
|
if (!CLUTTER_ACTOR_IS_MAPPED(CLUTTER_ACTOR (stage_glx)))
|
||||||
|
{
|
||||||
|
/* FIXME: This wont work if we support more states */
|
||||||
|
XDeleteProperty (stage_glx->xdpy,
|
||||||
|
stage_glx->xwin,
|
||||||
|
backend_glx->atom_WM_STATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clutter_stage_set_user_resizable (stage, TRUE);
|
||||||
|
|
||||||
|
send_wmspec_change_state(backend_glx,
|
||||||
|
stage_glx->xwin,
|
||||||
|
backend_glx->atom_WM_STATE_FULLSCREEN,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
/* reset the windows state - this isn't fun - see above */
|
||||||
|
if (!was_resizeable)
|
||||||
|
clutter_stage_set_user_resizable (stage, FALSE);
|
||||||
|
|
||||||
|
was_resizeable = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||||
|
@ -65,6 +65,7 @@ struct _ClutterStageGLX
|
|||||||
|
|
||||||
ClutterBackendGLX *backend;
|
ClutterBackendGLX *backend;
|
||||||
|
|
||||||
|
ClutterStageState state;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterStageGLXClass
|
struct _ClutterStageGLXClass
|
||||||
|
15
configure.ac
15
configure.ac
@ -205,19 +205,26 @@ case $clutterbackend in
|
|||||||
CLUTTER_COGL="gles"
|
CLUTTER_COGL="gles"
|
||||||
AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL/ES for rendering])
|
AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL/ES for rendering])
|
||||||
|
|
||||||
# try for libvincent first
|
# try for libvincent first (though its not so good)
|
||||||
PKG_CHECK_MODULES(EGL, libvincent, HAVE_OGLES=yes, HAVE_OGLES=no)
|
PKG_CHECK_MODULES(EGL, libvincent, HAVE_OGLES=yes, HAVE_OGLES=no)
|
||||||
if test "x$HAVE_OGLES" = "xno"; then
|
if test "x$HAVE_OGLES" = "xno"; then
|
||||||
AC_CHECK_HEADERS([GLES/egl.h GLES/gl.h],,
|
AC_CHECK_HEADERS([GLES/egl.h GLES/gl.h],,
|
||||||
[AC_MSG_ERROR([Unable to locate required GLES headers])])
|
[AC_MSG_ERROR([Unable to locate required GLES headers])])
|
||||||
|
|
||||||
|
# No libvincent so start checking for upper/lower case libgles_em
|
||||||
|
# The powervr sdk uses lower case.
|
||||||
|
|
||||||
AC_CHECK_LIB(GLES_CM, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no)
|
AC_CHECK_LIB(GLES_CM, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no)
|
||||||
|
|
||||||
if test "x$HAVE_LIBGLES" = "xno"; then
|
if test "x$HAVE_LIBGLES" = "xno"; then
|
||||||
|
|
||||||
|
AC_CHECK_LIB(gles_cm, eglInitialize, HAVE_LIBGLES=yes, HAVE_LIBGLES=no)
|
||||||
|
if test "x$HAVE_LIBGLES" = "xno"; then
|
||||||
AC_MSG_ERROR([GLES library not found and egl backend requested.]);
|
AC_MSG_ERROR([GLES library not found and egl backend requested.]);
|
||||||
|
fi
|
||||||
|
EGL_LIBS="-lgles_cm"
|
||||||
|
else
|
||||||
|
EGL_LIBS="-lGLES_CM"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
EGL_LIBS="-lGLES_CM"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
EGL_LIBS="$EGL_LIBS $X11_LIBS"
|
EGL_LIBS="$EGL_LIBS $X11_LIBS"
|
||||||
|
@ -1,6 +1,32 @@
|
|||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
gboolean IsFullScreen = FALSE;
|
||||||
|
|
||||||
|
static void
|
||||||
|
stage_state_cb (ClutterStage *stage,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
gchar *detail = (gchar*)data;
|
||||||
|
|
||||||
|
printf("[stage signal] %s\n", detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
blue_button_cb (ClutterActor *actor,
|
||||||
|
ClutterEvent *event,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
ClutterActor *stage;
|
||||||
|
|
||||||
|
stage = clutter_stage_get_default ();
|
||||||
|
|
||||||
|
if (IsFullScreen)
|
||||||
|
IsFullScreen = FALSE;
|
||||||
|
else
|
||||||
|
IsFullScreen = TRUE;
|
||||||
|
|
||||||
|
g_object_set (stage, "fullscreen", IsFullScreen, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
key_focus_in_cb (ClutterActor *actor,
|
key_focus_in_cb (ClutterActor *actor,
|
||||||
@ -104,6 +130,14 @@ main (int argc, char *argv[])
|
|||||||
|
|
||||||
stage = clutter_stage_get_default ();
|
stage = clutter_stage_get_default ();
|
||||||
g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage");
|
g_signal_connect (stage, "event", G_CALLBACK (input_cb), "stage");
|
||||||
|
g_signal_connect (stage, "fullscreen",
|
||||||
|
G_CALLBACK (stage_state_cb), "fullscreen");
|
||||||
|
g_signal_connect (stage, "unfullscreen",
|
||||||
|
G_CALLBACK (stage_state_cb), "unfullscreen");
|
||||||
|
g_signal_connect (stage, "activate",
|
||||||
|
G_CALLBACK (stage_state_cb), "activate");
|
||||||
|
g_signal_connect (stage, "deactivate",
|
||||||
|
G_CALLBACK (stage_state_cb), "deactivate");
|
||||||
|
|
||||||
focus_box = clutter_rectangle_new_with_color (&ncol);
|
focus_box = clutter_rectangle_new_with_color (&ncol);
|
||||||
clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
|
clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL);
|
||||||
@ -145,6 +179,7 @@ main (int argc, char *argv[])
|
|||||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
g_signal_connect (actor, "event", G_CALLBACK (input_cb), "blue box");
|
||||||
g_signal_connect (actor, "focus-in", G_CALLBACK (key_focus_in_cb),
|
g_signal_connect (actor, "focus-in", G_CALLBACK (key_focus_in_cb),
|
||||||
focus_box);
|
focus_box);
|
||||||
|
g_signal_connect (actor, "button-press-event", G_CALLBACK (blue_button_cb), NULL);
|
||||||
|
|
||||||
actor = clutter_rectangle_new_with_color (&ncol);
|
actor = clutter_rectangle_new_with_color (&ncol);
|
||||||
clutter_actor_set_size (actor, 400, 50);
|
clutter_actor_set_size (actor, 400, 50);
|
||||||
|
@ -2,6 +2,24 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
timeline_1_complete (ClutterTimeline *timeline)
|
||||||
|
{
|
||||||
|
g_debug ("1: Completed");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
timeline_2_complete (ClutterTimeline *timeline)
|
||||||
|
{
|
||||||
|
g_debug ("2: Completed");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
timeline_3_complete (ClutterTimeline *timeline)
|
||||||
|
{
|
||||||
|
g_debug ("3: Completed");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
timeline_1_new_frame_cb (ClutterTimeline *timeline, gint frame_no)
|
timeline_1_new_frame_cb (ClutterTimeline *timeline, gint frame_no)
|
||||||
{
|
{
|
||||||
@ -29,19 +47,30 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
clutter_init (&argc, &argv);
|
clutter_init (&argc, &argv);
|
||||||
|
|
||||||
timeline_1 = clutter_timeline_new (100, 50);
|
timeline_1 = clutter_timeline_new (10, 120);
|
||||||
timeline_2 = clutter_timeline_clone (timeline_1);
|
timeline_2 = clutter_timeline_clone (timeline_1);
|
||||||
timeline_3 = clutter_timeline_clone (timeline_1);
|
timeline_3 = clutter_timeline_clone (timeline_1);
|
||||||
|
|
||||||
g_signal_connect (timeline_1,
|
g_signal_connect (timeline_1,
|
||||||
"new-frame", G_CALLBACK (timeline_1_new_frame_cb),
|
"new-frame", G_CALLBACK (timeline_1_new_frame_cb),
|
||||||
NULL);
|
NULL);
|
||||||
|
g_signal_connect (timeline_1,
|
||||||
|
"completed", G_CALLBACK (timeline_1_complete),
|
||||||
|
NULL);
|
||||||
|
|
||||||
g_signal_connect (timeline_2,
|
g_signal_connect (timeline_2,
|
||||||
"new-frame", G_CALLBACK (timeline_2_new_frame_cb),
|
"new-frame", G_CALLBACK (timeline_2_new_frame_cb),
|
||||||
NULL);
|
NULL);
|
||||||
|
g_signal_connect (timeline_2,
|
||||||
|
"completed", G_CALLBACK (timeline_2_complete),
|
||||||
|
NULL);
|
||||||
|
|
||||||
g_signal_connect (timeline_3,
|
g_signal_connect (timeline_3,
|
||||||
"new-frame", G_CALLBACK (timeline_3_new_frame_cb),
|
"new-frame", G_CALLBACK (timeline_3_new_frame_cb),
|
||||||
NULL);
|
NULL);
|
||||||
|
g_signal_connect (timeline_3,
|
||||||
|
"completed", G_CALLBACK (timeline_3_complete),
|
||||||
|
NULL);
|
||||||
|
|
||||||
clutter_timeline_start (timeline_1);
|
clutter_timeline_start (timeline_1);
|
||||||
clutter_timeline_start (timeline_2);
|
clutter_timeline_start (timeline_2);
|
||||||
|
Loading…
Reference in New Issue
Block a user