diff --git a/clutter/clutter-animation.c b/clutter/clutter-animation.c index 73d5ae1ec..fa833732f 100644 --- a/clutter/clutter-animation.c +++ b/clutter/clutter-animation.c @@ -71,6 +71,7 @@ enum enum { + STARTED, COMPLETED, LAST_SIGNAL @@ -88,7 +89,9 @@ struct _ClutterAnimationPrivate guint loop : 1; guint duration; + ClutterTimeline *timeline; + guint timeline_started_id; guint timeline_completed_id; ClutterAlpha *alpha; @@ -132,6 +135,13 @@ clutter_animation_dispose (GObject *gobject) if (priv->timeline) { + if (priv->timeline_started_id) + { + g_signal_handler_disconnect (priv->timeline, + priv->timeline_started_id); + priv->timeline_started_id = 0; + } + if (priv->timeline_completed_id) { g_signal_handler_disconnect (priv->timeline, @@ -341,6 +351,24 @@ clutter_animation_class_init (ClutterAnimationClass *klass) CLUTTER_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_ALPHA, pspec); + /** + * ClutterAnimation::started: + * @animation: the animation that emitted the signal + * + * The ::started signal is emitted once the animation has been + * started + * + * Since: 1.0 + */ + animation_signals[STARTED] = + g_signal_new (I_("started"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterAnimationClass, started), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + /** * ClutterAniamtion::completed: * @animation: the animation that emitted the signal @@ -709,6 +737,13 @@ clutter_animation_get_interval (ClutterAnimation *animation, return g_hash_table_lookup (priv->properties, property_name); } +static void +on_timeline_started (ClutterTimeline *timeline, + ClutterAnimation *animation) +{ + g_signal_emit (animation, animation_signals[STARTED], 0); +} + static void on_timeline_completed (ClutterTimeline *timeline, ClutterAnimation *animation) @@ -1089,11 +1124,16 @@ clutter_animation_set_timeline (ClutterAnimation *animation, if (priv->timeline) { + if (priv->timeline_started_id) + g_signal_handler_disconnect (priv->timeline, + priv->timeline_started_id); + if (priv->timeline_completed_id) g_signal_handler_disconnect (priv->timeline, priv->timeline_completed_id); g_object_unref (priv->timeline); + priv->timeline_started_id = 0; priv->timeline_completed_id = 0; priv->timeline = 0; } @@ -1115,6 +1155,10 @@ clutter_animation_set_timeline (ClutterAnimation *animation, priv->timeline = g_object_ref (timeline); g_object_notify (G_OBJECT (animation), "timeline"); + priv->timeline_started_id = + g_signal_connect (timeline, "started", + G_CALLBACK (on_timeline_started), + animation); priv->timeline_completed_id = g_signal_connect (timeline, "completed", G_CALLBACK (on_timeline_completed), @@ -1425,12 +1469,13 @@ clutter_animation_setup_valist (ClutterAnimation *animation, GValue final = { 0, }; gchar *error = NULL; - if (G_UNLIKELY (g_str_equal (property_name, "signal::completed"))) + if (g_str_has_prefix (property_name, "signal::")) { + const gchar *signal_name = property_name + 8; GCallback callback = va_arg (var_args, GCallback); gpointer userdata = va_arg (var_args, gpointer); - g_signal_connect (animation, "completed", callback, userdata); + g_signal_connect (animation, signal_name, callback, userdata); } else { @@ -1647,7 +1692,8 @@ clutter_actor_animate_with_timeline (ClutterActor *actor, * * If a name argument starts with "signal::" the two following arguments * are used as callback function and userdata for a signal handler installed - * on the #ClutterAnimation object, for instance: + * on the #ClutterAnimation object for the specified signal name, for + * instance: * * |[ * @@ -1808,6 +1854,9 @@ clutter_actor_animate (ClutterActor *actor, * This is the vector-based variant of clutter_actor_animate(), useful * for language bindings. * + * Unlike clutter_actor_animate(), this function will not + * allow you to specify "signal::" names and callbacks. + * * Return value: (transfer none): a #ClutterAnimation object. The object is * owned by the #ClutterActor and should not be unreferenced with * g_object_unref() @@ -1881,6 +1930,9 @@ clutter_actor_animatev (ClutterActor *actor, * This is the vector-based variant of clutter_actor_animate_with_timeline(), * useful for language bindings. * + * Unlike clutter_actor_animate_with_timeline(), this function + * will not allow you to specify "signal::" names and callbacks. + * * Return value: (transfer none): a #ClutterAnimation object. The object is * owned by the #ClutterActor and should not be unreferenced with * g_object_unref() @@ -1943,6 +1995,9 @@ clutter_actor_animate_with_timelinev (ClutterActor *actor, * This is the vector-based variant of clutter_actor_animate_with_alpha(), * useful for language bindings. * + * Unlike clutter_actor_animate_with_alpha(), this function will + * not allow you to specify "signal::" names and callbacks. + * * Return value: (transfer none): a #ClutterAnimation object. The object is owned by the * #ClutterActor and should not be unreferenced with g_object_unref() * diff --git a/clutter/clutter-animation.h b/clutter/clutter-animation.h index b43088bd7..0990309ce 100644 --- a/clutter/clutter-animation.h +++ b/clutter/clutter-animation.h @@ -66,6 +66,7 @@ struct _ClutterAnimation /** * ClutterAnimationClass: + * @started: class handler for the #ClutterAnimation::started signal * @completed: class handler for the #ClutterAnimation::completed signal * * The #ClutterAnimationClass structure contains only private data and @@ -79,6 +80,7 @@ struct _ClutterAnimationClass GInitiallyUnownedClass parent_class; /*< public >*/ + void (* started) (ClutterAnimation *animation); void (* completed) (ClutterAnimation *animation); /*< private >*/