[gnome-shell] panel: programmatic anim. control of AnimatedIcon
- From: StÃphane DÃmurget <stef src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] panel: programmatic anim. control of AnimatedIcon
- Date: Sat, 17 Nov 2012 21:30:41 +0000 (UTC)
commit c48a246ccbee618956eefdb496770cc8d2694ec6
Author: StÃphane DÃmurget <stephane demurget free fr>
Date: Mon Nov 5 23:11:27 2012 +0100
panel: programmatic anim. control of AnimatedIcon
The AnimatedIcon does not have an API for controlling the animation but
relies on the :visible property changes to start and stop a timeout used
to update the frame.
This has the inconvenient of having a side effect when visible is set to
true multiple times, and is not really the API expected from such
component. Also, there is a race if it is displayed before the images
are loaded: there is no child yet and thus we get this._frame = NaN
which leads to a crash.
Switch to a play/stop API instead, and add a load event callback to the
TextureCache.load_slice_image to exactly know when we can start using
the images.
https://bugzilla.gnome.org/show_bug.cgi?id=687583
js/ui/panel.js | 39 +++++++++++++++++++++++++++++----------
src/st/st-texture-cache.c | 20 ++++++++++++++++----
src/st/st-texture-cache.h | 10 ++++++----
3 files changed, 51 insertions(+), 18 deletions(-)
---
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 9f36963..15a5db2 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -82,26 +82,34 @@ const AnimatedIcon = new Lang.Class({
_init: function(name, size) {
this.actor = new St.Bin({ visible: false });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
- this.actor.connect('notify::visible', Lang.bind(this, this._onVisibleNotify));
+ this._isLoaded = false;
+ this._isPlaying = false;
this._timeoutId = 0;
this._frame = 0;
- this._animations = St.TextureCache.get_default().load_sliced_image (global.datadir + '/theme/' + name, size, size);
+ this._animations = St.TextureCache.get_default().load_sliced_image (global.datadir + '/theme/' + name, size, size,
+ Lang.bind(this, this._animationsLoaded));
this.actor.set_child(this._animations);
},
- _disconnectTimeout: function() {
+ play: function() {
+ if (this._isLoaded && this._timeoutId == 0) {
+ if (this._frame == 0)
+ this._showFrame(0);
+
+ this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
+ }
+
+ this._isPlaying = true;
+ },
+
+ stop: function() {
if (this._timeoutId > 0) {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
}
- },
- _onVisibleNotify: function() {
- if (this.actor.visible)
- this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
- else
- this._disconnectTimeout();
+ this._isPlaying = false;
},
_showFrame: function(frame) {
@@ -121,8 +129,17 @@ const AnimatedIcon = new Lang.Class({
return true;
},
+ _animationsLoaded: function() {
+ this._isLoaded = true;
+
+ if (this._isPlaying) {
+ this._showFrame(0);
+ this._timeoutId = Mainloop.timeout_add(ANIMATED_ICON_UPDATE_TIMEOUT, Lang.bind(this, this._update));
+ }
+ },
+
_onDestroy: function() {
- this._disconnectTimeout();
+ this.stop();
}
});
@@ -367,6 +384,7 @@ const AppMenuButton = new Lang.Class({
transition: "easeOutQuad",
onCompleteScope: this,
onComplete: function() {
+ this._spinner.stop();
this._spinner.actor.opacity = 255;
this._spinner.actor.hide();
}
@@ -376,6 +394,7 @@ const AppMenuButton = new Lang.Class({
startAnimation: function() {
this._stop = false;
this.actor.reactive = false;
+ this._spinner.play();
this._spinner.actor.show();
},
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
index d178490..c562a77 100644
--- a/src/st/st-texture-cache.c
+++ b/src/st/st-texture-cache.c
@@ -1073,6 +1073,8 @@ typedef struct {
gchar *path;
gint grid_width, grid_height;
ClutterActor *actor;
+ GFunc load_callback;
+ gpointer load_callback_data;
} AsyncImageData;
static void
@@ -1089,6 +1091,7 @@ on_sliced_image_loaded (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
+ GObject *cache = source_object;
AsyncImageData *data = (AsyncImageData *)user_data;
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
GList *list;
@@ -1102,6 +1105,9 @@ on_sliced_image_loaded (GObject *source_object,
clutter_actor_hide (actor);
clutter_actor_add_child (data->actor, actor);
}
+
+ if (data->load_callback != NULL)
+ data->load_callback (cache, data->load_callback_data);
}
static void
@@ -1156,6 +1162,8 @@ load_sliced_image (GSimpleAsyncResult *result,
* @path: Path to a filename
* @grid_width: Width in pixels
* @grid_height: Height in pixels
+ * @load_callback: (scope async) (allow-none): Function called when the image is loaded, or %NULL
+ * @user_data: Data to pass to the load callback
*
* This function reads a single image file which contains multiple images internally.
* The image file will be divided using @grid_width and @grid_height;
@@ -1165,10 +1173,12 @@ load_sliced_image (GSimpleAsyncResult *result,
* Returns: (transfer none): A new #ClutterActor
*/
ClutterActor *
-st_texture_cache_load_sliced_image (StTextureCache *cache,
- const gchar *path,
- gint grid_width,
- gint grid_height)
+st_texture_cache_load_sliced_image (StTextureCache *cache,
+ const gchar *path,
+ gint grid_width,
+ gint grid_height,
+ GFunc load_callback,
+ gpointer user_data)
{
AsyncImageData *data;
GSimpleAsyncResult *result;
@@ -1179,6 +1189,8 @@ st_texture_cache_load_sliced_image (StTextureCache *cache,
data->grid_height = grid_height;
data->path = g_strdup (path);
data->actor = actor;
+ data->load_callback = load_callback;
+ data->load_callback_data = user_data;
g_object_ref (G_OBJECT (actor));
result = g_simple_async_result_new (G_OBJECT (cache), on_sliced_image_loaded, data, st_texture_cache_load_sliced_image);
diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h
index 8db438b..c913b39 100644
--- a/src/st/st-texture-cache.h
+++ b/src/st/st-texture-cache.h
@@ -69,10 +69,12 @@ GType st_texture_cache_get_type (void) G_GNUC_CONST;
StTextureCache* st_texture_cache_get_default (void);
ClutterActor *
-st_texture_cache_load_sliced_image (StTextureCache *cache,
- const gchar *path,
- gint grid_width,
- gint grid_height);
+st_texture_cache_load_sliced_image (StTextureCache *cache,
+ const gchar *path,
+ gint grid_width,
+ gint grid_height,
+ GFunc load_callback,
+ gpointer user_data);
ClutterActor *st_texture_cache_bind_pixbuf_property (StTextureCache *cache,
GObject *object,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]