StIcon: don't show the icon until fully loaded

When updating the texture, keep the old one until the new one is
loaded.

https://bugzilla.gnome.org/show_bug.cgi?id=634814
This commit is contained in:
Giovanni Campagna 2010-11-30 16:19:27 +01:00
parent e425a183f7
commit a70f1f449b

View File

@ -49,6 +49,8 @@ G_DEFINE_TYPE (StIcon, st_icon, ST_TYPE_WIDGET)
struct _StIconPrivate struct _StIconPrivate
{ {
ClutterActor *icon_texture; ClutterActor *icon_texture;
ClutterActor *pending_texture;
guint opacity_handler_id;
GIcon *gicon; GIcon *gicon;
gchar *icon_name; gchar *icon_name;
@ -143,6 +145,13 @@ st_icon_dispose (GObject *gobject)
priv->icon_texture = NULL; priv->icon_texture = NULL;
} }
if (priv->pending_texture)
{
clutter_actor_destroy (priv->pending_texture);
g_object_unref (priv->pending_texture);
priv->icon_texture = NULL;
}
if (priv->gicon) if (priv->gicon)
{ {
g_object_unref (priv->gicon); g_object_unref (priv->gicon);
@ -401,20 +410,62 @@ on_pixbuf_changed (ClutterTexture *texture,
} }
static void static void
st_icon_update (StIcon *icon) st_icon_finish_update (StIcon *icon)
{ {
StIconPrivate *priv = icon->priv; StIconPrivate *priv = icon->priv;
StThemeNode *theme_node;
StTextureCache *cache;
/* Get rid of the old one */
if (priv->icon_texture) if (priv->icon_texture)
{ {
clutter_actor_destroy (priv->icon_texture); clutter_actor_destroy (priv->icon_texture);
priv->icon_texture = NULL; priv->icon_texture = NULL;
} }
/* Try to lookup the new one */ if (priv->pending_texture)
{
priv->icon_texture = priv->pending_texture;
priv->pending_texture = NULL;
clutter_actor_set_parent (priv->icon_texture, CLUTTER_ACTOR (icon));
/* Remove the temporary ref we added */
g_object_unref (priv->icon_texture);
st_icon_update_shadow_material (icon);
/* "pixbuf-change" is actually a misnomer for "texture-changed" */
g_signal_connect (priv->icon_texture, "pixbuf-change",
G_CALLBACK (on_pixbuf_changed), icon);
}
}
static void
opacity_changed_cb (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
StIcon *icon = user_data;
StIconPrivate *priv = icon->priv;
g_signal_handler_disconnect (priv->pending_texture, priv->opacity_handler_id);
priv->opacity_handler_id = 0;
st_icon_finish_update (icon);
}
static void
st_icon_update (StIcon *icon)
{
StIconPrivate *priv = icon->priv;
StThemeNode *theme_node;
StTextureCache *cache;
if (priv->pending_texture)
{
clutter_actor_destroy (priv->pending_texture);
g_object_unref (priv->pending_texture);
priv->pending_texture = NULL;
priv->opacity_handler_id = 0;
}
theme_node = st_widget_peek_theme_node (ST_WIDGET (icon)); theme_node = st_widget_peek_theme_node (ST_WIDGET (icon));
if (theme_node == NULL) if (theme_node == NULL)
return; return;
@ -422,29 +473,41 @@ st_icon_update (StIcon *icon)
cache = st_texture_cache_get_default (); cache = st_texture_cache_get_default ();
if (priv->gicon) if (priv->gicon)
{ {
priv->icon_texture = st_texture_cache_load_gicon (cache, priv->pending_texture = st_texture_cache_load_gicon (cache,
(priv->icon_type != ST_ICON_APPLICATION && (priv->icon_type != ST_ICON_APPLICATION &&
priv->icon_type != ST_ICON_DOCUMENT) ? priv->icon_type != ST_ICON_DOCUMENT) ?
theme_node : NULL, theme_node : NULL,
priv->gicon, priv->gicon,
priv->icon_size); priv->icon_size);
} }
else if (priv->icon_name) else if (priv->icon_name)
{ {
priv->icon_texture = st_texture_cache_load_icon_name (cache, priv->pending_texture = st_texture_cache_load_icon_name (cache,
theme_node, theme_node,
priv->icon_name, priv->icon_name,
priv->icon_type, priv->icon_type,
priv->icon_size); priv->icon_size);
} }
if (priv->icon_texture)
{
st_icon_update_shadow_material (icon);
clutter_actor_set_parent (priv->icon_texture, CLUTTER_ACTOR (icon));
/* "pixbuf-change" is actually a misnomer for "texture-changed" */ if (priv->pending_texture)
g_signal_connect (priv->icon_texture, "pixbuf-change", {
G_CALLBACK (on_pixbuf_changed), icon); g_object_ref_sink (priv->pending_texture);
if (clutter_actor_get_opacity (priv->pending_texture) != 0 || priv->icon_texture == NULL)
{
/* This icon is ready for showing, or nothing else is already showing */
st_icon_finish_update (icon);
}
else
{
/* Will be shown when fully loaded */
priv->opacity_handler_id = g_signal_connect (priv->pending_texture, "notify::opacity", G_CALLBACK (opacity_changed_cb), icon);
}
}
else if (priv->icon_texture)
{
clutter_actor_destroy (priv->icon_texture);
priv->icon_texture = NULL;
} }
} }