[Xfce4-commits] [apps/xfdashboard] 01/01: Adding support to animate actor when a class or a pseudo-class was added or removed.

noreply at xfce.org noreply at xfce.org
Fri Jan 31 15:47:27 CET 2020


This is an automated email from the git hooks/post-receive script.

n   o   m   a   d       p   u   s   h   e   d       a       c   o   m   m   i   t       t   o       b   r   a   n   c   h       m   a   s   t   e   r   
   in repository apps/xfdashboard.

commit 232b866b6a3aff2f44ae6f3b070967a8161a16c3
Author: Stephan Haller <nomad at froevel.de>
Date:   Fri Jan 31 15:46:47 2020 +0100

    Adding support to animate actor when a class or a pseudo-class was added or removed.
---
 libxfdashboard/actor.c           | 245 ++++++++++++++++++++++++++++++++++++++-
 libxfdashboard/animation.c       |  45 ++++---
 libxfdashboard/theme-animation.c |   6 -
 3 files changed, 272 insertions(+), 24 deletions(-)

diff --git a/libxfdashboard/actor.c b/libxfdashboard/actor.c
index 89531c1..a285406 100644
--- a/libxfdashboard/actor.c
+++ b/libxfdashboard/actor.c
@@ -32,6 +32,7 @@
 #include <libxfdashboard/application.h>
 #include <libxfdashboard/stylable.h>
 #include <libxfdashboard/focusable.h>
+#include <libxfdashboard/animation.h>
 #include <libxfdashboard/utils.h>
 #include <libxfdashboard/compat.h>
 #include <libxfdashboard/debug.h>
@@ -59,6 +60,7 @@ struct _XfdashboardActorPrivate
 	GHashTable		*lastThemeStyleSet;
 	gboolean		forceStyleRevalidation;
 	gboolean		isFirstParent;
+	GSList			*animations;
 };
 
 /* Properties */
@@ -79,16 +81,35 @@ enum
 static GParamSpec* XfdashboardActorProperties[PROP_LAST]={ 0, };
 
 /* IMPLEMENTATION: Private variables and methods */
-static GParamSpecPool		*_xfdashboard_actor_stylable_properties_pool=NULL;
+typedef struct _XfdashboardActorAnimationEntry		XfdashboardActorAnimationEntry;
+struct _XfdashboardActorAnimationEntry
+{
+	gchar					*signal;
+	XfdashboardAnimation	*animation;
+};
 
 #define XFDASHBOARD_ACTOR_PARAM_SPEC_REF		(_xfdashboard_actor_param_spec_ref_quark())
 
+static GParamSpecPool		*_xfdashboard_actor_stylable_properties_pool=NULL;
+
+
 /* Quark declarations */
 static GQuark _xfdashboard_actor_param_spec_ref_quark(void)
 {
 	return(g_quark_from_static_string("xfdashboard-actor-param-spec-ref-quark"));
 }
 
+
+/* Free an animation entry */
+static void _xfdashboard_actor_animation_entry_free(XfdashboardActorAnimationEntry *inData)
+{
+	g_return_if_fail(inData);
+
+	/* Release allocated resources */
+	if(inData->signal) g_free(inData->signal);
+	g_free(inData);
+}
+
 /* Invalidate all stylable children recursively beginning at given actor */
 static void _xfdashboard_actor_invalidate_recursive(ClutterActor *inActor)
 {
@@ -708,6 +729,218 @@ static void _xfdashboard_actor_stylable_invalidate(XfdashboardStylable *inStylab
 	g_object_thaw_notify(G_OBJECT(self));
 }
 
+/* Animation has completed, so remove from list */
+static void _xfdashboard_actor_animation_done(XfdashboardAnimation *inAnimation,
+												gpointer inUserData)
+{
+	XfdashboardActor				*self;
+	XfdashboardActorPrivate			*priv;
+	GSList							*iter;
+	XfdashboardActorAnimationEntry	*data;
+
+	g_return_if_fail(XFDASHBOARD_IS_ANIMATION(inAnimation));
+	g_return_if_fail(XFDASHBOARD_IS_ACTOR(inUserData));
+
+	self=XFDASHBOARD_ACTOR(inUserData);
+	priv=self->priv;
+
+	/* Lookup animation done in list of animation and remove animation entry */
+	for(iter=priv->animations; iter; iter=g_slist_next(iter))
+	{
+		/* Get animation entry at iterator */
+		data=(XfdashboardActorAnimationEntry*)iter->data;
+		if(!data) continue;
+
+		/* Check if animation entry matches the animation done */
+		if(data->animation==inAnimation)
+		{
+			XFDASHBOARD_DEBUG(self, ANIMATION,
+									"Removing stopped animation '%s'",
+									xfdashboard_animation_get_id(data->animation));
+
+			/* Remove entry from list */
+			_xfdashboard_actor_animation_entry_free(data);
+			priv->animations=g_slist_delete_link(priv->animations, iter);
+
+			/* An animation with equal pointer can be stored only once, so
+			 * stop further iteration.
+			 */
+			break;
+		}
+	}
+}
+
+/* Remove animations for signal and (pseudo-)class */
+static void _xfdashboard_actor_remove_animation(XfdashboardStylable *inStylable,
+												const gchar *inSignalPrefix,
+												const gchar *inClass)
+{
+	XfdashboardActor				*self;
+	XfdashboardActorPrivate			*priv;
+	gchar							*animationSignal;
+	GSList							*iter;
+	XfdashboardActorAnimationEntry	*data;
+
+	g_return_if_fail(XFDASHBOARD_IS_ACTOR(inStylable));
+
+	self=XFDASHBOARD_ACTOR(inStylable);
+	priv=self->priv;
+
+	/* Get signal to lookup animation */
+	animationSignal=g_strdup_printf("%s:%s", inSignalPrefix, inClass);
+
+	/* Iterate through list of animation and lookup animation for signal. If an
+	 * animation is found, stop it. It will be remove from list of animations
+	 * automatically.
+	 */
+	for(iter=priv->animations; iter; iter=g_slist_next(iter))
+	{
+		/* Get animation entry at iterator */
+		data=(XfdashboardActorAnimationEntry*)iter->data;
+		if(!data) continue;
+
+		/* Check if animation entry matches the signal to lookup */
+		if(g_strcmp0(data->signal, animationSignal)==0)
+		{
+			XFDASHBOARD_DEBUG(self, ANIMATION,
+									"Stopping and removing animation '%s' for signal '%s'",
+									xfdashboard_animation_get_id(data->animation),
+									animationSignal);
+
+			/* Stop animation by unreffing object instance */
+			g_object_unref(data->animation);
+		}
+	}
+
+	/* Release allocated resources */
+	g_free(animationSignal);
+}
+
+/* Lookup animations for signal and (pseudo-)class and run animation at actor */
+static void _xfdashboard_actor_add_animation(XfdashboardStylable *inStylable,
+												const gchar *inSignalPrefix,
+												const gchar *inClass)
+{
+	XfdashboardActor				*self;
+	XfdashboardActorPrivate			*priv;
+	XfdashboardAnimation			*animation;
+	gchar							*animationSignal;
+	XfdashboardActorAnimationEntry	*data;
+
+	g_return_if_fail(XFDASHBOARD_IS_ACTOR(inStylable));
+
+	self=XFDASHBOARD_ACTOR(inStylable);
+	priv=self->priv;
+
+	/* Get signal to lookup animation */
+	animationSignal=g_strdup_printf("%s:%s", inSignalPrefix, inClass);
+
+	/* Lookup animation for signal-(pseudo-)class combination and if any found
+	 * (i.e. has an ID) add it to list of animations of actor and run it.
+	 */
+	animation=xfdashboard_animation_new(XFDASHBOARD_ACTOR(self), animationSignal);
+	if(!xfdashboard_animation_get_id(animation))
+	{
+		/* Empty or invalid animation, so release allocated resources and return */
+		g_object_unref(animation);
+		g_free(animationSignal);
+
+		return;
+	}
+
+	/* Check for duplicate animation */
+	if(clutter_actor_get_transition(CLUTTER_ACTOR(self), xfdashboard_animation_get_id(animation)))
+	{
+		XFDASHBOARD_DEBUG(self, ANIMATION,
+								"Duplicate animation found for signal '%s'",
+								animationSignal);
+
+		/* Release allocated resources */
+		g_object_unref(animation);
+		g_free(animationSignal);
+
+		return;
+	}
+
+	/* Create animation entry data and add to list of animations */
+	data=g_new0(XfdashboardActorAnimationEntry, 1);
+	if(!data)
+	{
+		g_critical(_("Cannot allocate memory for animation entry for animation '%s' with signal '%s'"),
+					xfdashboard_animation_get_id(animation),
+					animationSignal);
+
+		/* Release allocated resources */
+		g_object_unref(animation);
+		g_free(animationSignal);
+
+		return;
+	}
+
+	data->signal=g_strdup(animationSignal);
+	data->animation=animation;
+
+	priv->animations=g_slist_prepend(priv->animations, data);
+
+	/* Start animation */
+	xfdashboard_animation_run(animation, _xfdashboard_actor_animation_done, self);
+	XFDASHBOARD_DEBUG(self, ANIMATION,
+							"Found and starting animation '%s' for signal '%s'",
+							xfdashboard_animation_get_id(animation),
+							animationSignal);
+
+	/* Release allocated resources */
+	g_free(animationSignal);
+}
+
+/* Signal handler for "class-added" signal of stylable interface */
+static void _xfdashboard_actor_stylable_class_added(XfdashboardStylable *inStylable, const gchar *inClass)
+{
+	g_return_if_fail(XFDASHBOARD_IS_ACTOR(inStylable));
+
+	/* Remove any animation that was added when this class was removed */
+	_xfdashboard_actor_remove_animation(inStylable, "class-removed", inClass);
+
+	/* Create animation for this class added */
+	_xfdashboard_actor_add_animation(inStylable, "class-added", inClass);
+}
+
+/* Signal handler for "class-removed" signal of stylable interface */
+static void _xfdashboard_actor_stylable_class_removed(XfdashboardStylable *inStylable, const gchar *inClass)
+{
+	g_return_if_fail(XFDASHBOARD_IS_ACTOR(inStylable));
+
+	/* Remove any animation that was added when this class was added */
+	_xfdashboard_actor_remove_animation(inStylable, "class-added", inClass);
+
+	/* Create animation for this class removed */
+	_xfdashboard_actor_add_animation(inStylable, "class-removed", inClass);
+}
+
+/* Signal handler for "pseudo-class-added" signal of stylable interface */
+static void _xfdashboard_actor_stylable_pseudo_class_added(XfdashboardStylable *inStylable, const gchar *inClass)
+{
+	g_return_if_fail(XFDASHBOARD_IS_ACTOR(inStylable));
+
+	/* Remove any animation that was added when this pseudo-class was removed */
+	_xfdashboard_actor_remove_animation(inStylable, "pseudo-class-removed", inClass);
+
+	/* Create animation for this pseudo-class added */
+	_xfdashboard_actor_add_animation(inStylable, "pseudo-class-added", inClass);
+}
+
+/* Signal handler for "pseudo-class-removed" signal of stylable interface */
+static void _xfdashboard_actor_stylable_pseudo_class_removed(XfdashboardStylable *inStylable, const gchar *inClass)
+{
+	g_return_if_fail(XFDASHBOARD_IS_ACTOR(inStylable));
+
+	/* Remove any animation that was added when this pseudo-class was added */
+	_xfdashboard_actor_remove_animation(inStylable, "pseudo-class-added", inClass);
+
+	/* Create animation for this pseudo-class removed */
+	_xfdashboard_actor_add_animation(inStylable, "pseudo-class-removed", inClass);
+}
+
 /* Interface initialization
  * Set up default functions
  */
@@ -718,8 +951,12 @@ static void _xfdashboard_actor_stylable_iface_init(XfdashboardStylableInterface
 	iface->get_parent=_xfdashboard_actor_stylable_get_parent;
 	iface->get_classes=_xfdashboard_actor_stylable_get_classes;
 	iface->set_classes=_xfdashboard_actor_stylable_set_classes;
+	iface->class_added=_xfdashboard_actor_stylable_class_added;
+	iface->class_removed=_xfdashboard_actor_stylable_class_removed;
 	iface->get_pseudo_classes=_xfdashboard_actor_stylable_get_pseudo_classes;
 	iface->set_pseudo_classes=_xfdashboard_actor_stylable_set_pseudo_classes;
+	iface->pseudo_class_added=_xfdashboard_actor_stylable_pseudo_class_added;
+	iface->pseudo_class_removed=_xfdashboard_actor_stylable_pseudo_class_removed;
 	iface->invalidate=_xfdashboard_actor_stylable_invalidate;
 }
 
@@ -899,6 +1136,11 @@ static void _xfdashboard_actor_dispose(GObject *inObject)
 		priv->lastThemeStyleSet=NULL;
 	}
 
+	if(priv->animations)
+	{
+		// TODO: Release list of animations
+	}
+
 	/* Call parent's class dispose method */
 	G_OBJECT_CLASS(xfdashboard_actor_parent_class)->dispose(inObject);
 }
@@ -1056,6 +1298,7 @@ void xfdashboard_actor_init(XfdashboardActor *self)
 	priv->stylePseudoClasses=NULL;
 	priv->lastThemeStyleSet=NULL;
 	priv->isFirstParent=TRUE;
+	priv->animations=NULL;
 
 	/* Connect signals */
 	g_signal_connect(self, "notify::mapped", G_CALLBACK(_xfdashboard_actor_on_mapped_changed), NULL);
diff --git a/libxfdashboard/animation.c b/libxfdashboard/animation.c
index a70a71f..387a228 100644
--- a/libxfdashboard/animation.c
+++ b/libxfdashboard/animation.c
@@ -658,26 +658,37 @@ void xfdashboard_animation_run(XfdashboardAnimation *self,
 	priv->doneCallback=inCallback;
 	priv->doneUserData=inUserData;
 
-	/* Add all transition to their actors now */
-	for(iter=priv->entries; iter; iter=g_slist_next(iter))
+	/* Add all transition to their actors now if any available ... */
+	if(priv->entries)
 	{
-		/* Get entry */
-		entry=(XfdashboardAnimationEntry*)iter->data;
-		if(!entry) continue;
+		for(iter=priv->entries; iter; iter=g_slist_next(iter))
+		{
+			/* Get entry */
+			entry=(XfdashboardAnimationEntry*)iter->data;
+			if(!entry) continue;
 
-		/* Add transition to actor which will start immediately */
-		clutter_actor_add_transition(entry->actor, priv->id, entry->transition);
+			/* Add transition to actor which will start immediately */
+			clutter_actor_add_transition(entry->actor, priv->id, entry->transition);
 #ifdef DEBUG
-		XFDASHBOARD_DEBUG(self, ANIMATION,
-							"Animation '%s' added transition %p to actor %s@%p",
-							priv->id,
-							entry->transition,
-							G_OBJECT_TYPE_NAME(entry->actor),
-							entry->actor);
+			XFDASHBOARD_DEBUG(self, ANIMATION,
+								"Animation '%s' added transition %p to actor %s@%p",
+								priv->id,
+								entry->transition,
+								G_OBJECT_TYPE_NAME(entry->actor),
+								entry->actor);
 #endif
-	}
+		}
 
-	XFDASHBOARD_DEBUG(self, ANIMATION,
-						"Started animation '%s'",
-						priv->id);
+		XFDASHBOARD_DEBUG(self, ANIMATION,
+							"Started animation '%s'",
+							priv->id);
+	}
+		/* ... otherwise destroy empty animation immediately to get callback
+		 * function called and to avoid memory leaks.
+		 */
+		else
+		{
+			/* Destroy empty animation */
+			g_object_unref(self);
+		}
 }
diff --git a/libxfdashboard/theme-animation.c b/libxfdashboard/theme-animation.c
index d21671f..4203d8d 100644
--- a/libxfdashboard/theme-animation.c
+++ b/libxfdashboard/theme-animation.c
@@ -1168,12 +1168,6 @@ static void _xfdashboard_theme_animation_parse_trigger_start(GMarkupParseContext
 			return;
 		}
 
-		if(!_xfdashboard_theme_animation_string_to_gint(timelineDelayText, &timelineDelay, &error))
-		{
-			g_propagate_error(outError, error);
-			return;
-		}
-
 		timelineMode=xfdashboard_get_enum_value_from_nickname(CLUTTER_TYPE_ANIMATION_MODE, timelineModeText);
 		if(timelineMode==G_MININT)
 		{

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list