aboutsummaryrefslogtreecommitdiffstats
path: root/lib/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'lib/widgets')
-rw-r--r--lib/widgets/ephy-spinner.c334
-rw-r--r--lib/widgets/testspinner.c2
2 files changed, 172 insertions, 164 deletions
diff --git a/lib/widgets/ephy-spinner.c b/lib/widgets/ephy-spinner.c
index 964c8e36e..c713fb9ee 100644
--- a/lib/widgets/ephy-spinner.c
+++ b/lib/widgets/ephy-spinner.c
@@ -68,6 +68,12 @@ struct _EphySpinnerCache
#define EPHY_SPINNER_CACHE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_SPINNER_CACHE, EphySpinnerCachePrivate))
+struct _EphySpinnerCachePrivate
+{
+ /* Hash table of GdkScreen -> EphySpinnerCacheData */
+ GHashTable *hash;
+};
+
typedef struct
{
GtkIconSize size;
@@ -77,25 +83,22 @@ typedef struct
GList *images;
} EphySpinnerImages;
+#define LAST_ICON_SIZE GTK_ICON_SIZE_DIALOG + 1
+#define SPINNER_ICON_NAME "gnome-spinner"
+#define SPINNER_REST_ICON_NAME "gnome-spinner-rest"
+#define EPHY_SPINNER_IMAGES_INVALID ((EphySpinnerImages *) 0x1)
+
typedef struct
{
GdkScreen *screen;
GtkIconTheme *icon_theme;
- EphySpinnerImages *originals;
- /* List of EphySpinnerImages scaled to different sizes */
- GList *images;
+ EphySpinnerImages *images[LAST_ICON_SIZE];
} EphySpinnerCacheData;
-struct _EphySpinnerCachePrivate
-{
- /* Hash table of GdkScreen -> EphySpinnerCacheData */
- GHashTable *hash;
-};
-
static void ephy_spinner_cache_class_init (EphySpinnerCacheClass *klass);
static void ephy_spinner_cache_init (EphySpinnerCache *cache);
-static GObjectClass *cache_parent_class = NULL;
+static GObjectClass *ephy_spinner_cache_parent_class = NULL;
static GType
ephy_spinner_cache_get_type (void)
@@ -131,6 +134,8 @@ ephy_spinner_images_free (EphySpinnerImages *images)
if (images != NULL)
{
g_list_foreach (images->images, (GFunc) g_object_unref, NULL);
+ g_list_free (images->images);
+
g_object_unref (images->quiescent_pixbuf);
g_free (images);
@@ -156,13 +161,23 @@ ephy_spinner_images_copy (EphySpinnerImages *images)
static void
ephy_spinner_cache_data_unload (EphySpinnerCacheData *data)
{
+ GtkIconSize size;
+ EphySpinnerImages *images;
+
g_return_if_fail (data != NULL);
LOG ("EphySpinnerDataCache unload for screen %p", data->screen);
- g_list_foreach (data->images, (GFunc) ephy_spinner_images_free, NULL);
- data->images = NULL;
- data->originals = NULL;
+ for (size = GTK_ICON_SIZE_INVALID; size < LAST_ICON_SIZE; ++size)
+ {
+ images = data->images[size];
+ if (images != NULL && images != EPHY_SPINNER_IMAGES_INVALID)
+ {
+ ephy_spinner_images_free (images);
+ }
+
+ data->images[size] = NULL;
+ }
}
static GdkPixbuf *
@@ -187,60 +202,106 @@ extract_frame (GdkPixbuf *grid_pixbuf,
return pixbuf;
}
-static void
-ephy_spinner_cache_data_load (EphySpinnerCacheData *data)
+static GdkPixbuf *
+scale_to_size (GdkPixbuf *pixbuf,
+ int dw,
+ int dh)
+{
+ GdkPixbuf *result;
+ int pw, ph;
+
+ g_return_val_if_fail (pixbuf != NULL, NULL);
+
+ pw = gdk_pixbuf_get_width (pixbuf);
+ ph = gdk_pixbuf_get_height (pixbuf);
+
+ if (pw != dw || ph != dh)
+ {
+ result = gdk_pixbuf_scale_simple (pixbuf, dw, dh,
+ GDK_INTERP_BILINEAR);
+ g_object_unref (pixbuf);
+ return result;
+ }
+
+ return pixbuf;
+}
+
+static EphySpinnerImages *
+ephy_spinner_images_load (GdkScreen *screen,
+ GtkIconTheme *icon_theme,
+ GtkIconSize icon_size)
{
EphySpinnerImages *images;
+ GdkPixbuf *rest_pixbuf = NULL;
GdkPixbuf *icon_pixbuf, *pixbuf;
- GtkIconInfo *icon_info;
- int grid_width, grid_height, x, y, size, h, w;
+ GtkIconInfo *icon_info = NULL;
+ int grid_width, grid_height, x, y, requested_size, size, h, w, isw, ish;
const char *icon;
+ GList *list = NULL, *l;
- g_return_if_fail (data != NULL);
+ LOG ("EphySpinnerCacheData loading for screen %p at size %d", screen, icon_size);
- LOG ("EphySpinnerCacheData loading for screen %p", data->screen);
+ START_PROFILER ("loading spinner animation")
- ephy_spinner_cache_data_unload (data);
+ if (!gtk_icon_size_lookup_for_settings (gtk_settings_get_for_screen (screen),
+ icon_size, &isw, &ish)) goto loser;
- START_PROFILER ("loading spinner animation")
+ requested_size = MAX (ish, isw);
- /* Load the animation */
- icon_info = gtk_icon_theme_lookup_icon (data->icon_theme,
- "gnome-spinner", -1, 0);
+ /* Load the rest icon */
+ icon_info = gtk_icon_theme_lookup_icon (icon_theme,
+ SPINNER_REST_ICON_NAME,
+ requested_size, 0);
if (icon_info == NULL)
{
- STOP_PROFILER ("loading spinner animation")
+ g_warning ("Throbber rest icon not found");
+ goto loser;
+ }
- g_warning ("Throbber animation not found\n");
- return;
+ size = gtk_icon_info_get_base_size (icon_info);
+ icon = gtk_icon_info_get_filename (icon_info);
+ if (icon == NULL) goto loser;
+
+ rest_pixbuf = gdk_pixbuf_new_from_file (icon, NULL);
+ gtk_icon_info_free (icon_info);
+
+ if (rest_pixbuf == NULL)
+ {
+ g_warning ("Could not load spinner rest icon");
+ goto loser;
+ }
+
+ if (size > requested_size)
+ {
+ rest_pixbuf = scale_to_size (rest_pixbuf, isw, ish);
+ }
+
+ /* Load the animation */
+ icon_info = gtk_icon_theme_lookup_icon (icon_theme,
+ SPINNER_ICON_NAME,
+ requested_size, 0);
+ if (icon_info == NULL)
+ {
+ g_warning ("Throbber animation not found");
+ goto loser;
}
size = gtk_icon_info_get_base_size (icon_info);
icon = gtk_icon_info_get_filename (icon_info);
- g_return_if_fail (icon != NULL);
+ if (icon == NULL) goto loser;
icon_pixbuf = gdk_pixbuf_new_from_file (icon, NULL);
+ gtk_icon_info_free (icon_info);
+
if (icon_pixbuf == NULL)
{
- STOP_PROFILER ("loading spinner animation")
-
- g_warning ("Could not load the spinner file\n");
- gtk_icon_info_free (icon_info);
- return;
+ g_warning ("Could not load the spinner file");
+ goto loser;
}
grid_width = gdk_pixbuf_get_width (icon_pixbuf);
grid_height = gdk_pixbuf_get_height (icon_pixbuf);
- images = g_new (EphySpinnerImages, 1);
- data->images = g_list_prepend (NULL, images);
- data->originals = images;
-
- images->size = GTK_ICON_SIZE_INVALID;
- images->width = images->height = size;
- images->images = NULL;
- images->quiescent_pixbuf = NULL;
-
for (y = 0; y < grid_height; y += size)
{
for (x = 0; x < grid_width ; x += size)
@@ -249,55 +310,54 @@ ephy_spinner_cache_data_load (EphySpinnerCacheData *data)
if (pixbuf)
{
- images->images =
- g_list_prepend (images->images, pixbuf);
+ list = g_list_prepend (list, pixbuf);
}
else
{
- g_warning ("Cannot extract frame from the grid\n");
+ g_warning ("Cannot extract frame (%d, %d) from the grid\n", x, y);
}
}
}
- images->images = g_list_reverse (images->images);
- gtk_icon_info_free (icon_info);
+ list = g_list_reverse (list);
g_object_unref (icon_pixbuf);
- /* Load the rest icon */
- icon_info = gtk_icon_theme_lookup_icon (data->icon_theme,
- "gnome-spinner-rest", -1, 0);
- if (icon_info == NULL)
- {
- STOP_PROFILER ("loading spinner animation")
+ if (list == NULL) goto loser;
- g_warning ("Throbber rest icon not found\n");
- return;
+ if (size > requested_size)
+ {
+ for (l = list; l != NULL; l = l->next)
+ {
+ l->data = scale_to_size (l->data, isw, ish);
+ }
}
+
+ /* Now we've successfully got all the data */
+ images = g_new (EphySpinnerImages, 1);
- size = gtk_icon_info_get_base_size (icon_info);
- icon = gtk_icon_info_get_filename (icon_info);
- g_return_if_fail (icon != NULL);
+ images->size = icon_size;
+ images->width = images->height = requested_size;
+ images->images = list;
+ images->quiescent_pixbuf = rest_pixbuf;
- icon_pixbuf = gdk_pixbuf_new_from_file (icon, NULL);
- gtk_icon_info_free (icon_info);
+ STOP_PROFILER ("loading spinner animation")
- if (icon_pixbuf == NULL)
- {
- STOP_PROFILER ("loading spinner animation")
+ return images;
- g_warning ("Could not load spinner rest icon\n");
- ephy_spinner_images_free (images);
- return;
+loser:
+ if (icon_info)
+ {
+ gtk_icon_info_free (icon_info);
}
-
- images->quiescent_pixbuf = icon_pixbuf;
-
- w = gdk_pixbuf_get_width (icon_pixbuf);
- h = gdk_pixbuf_get_height (icon_pixbuf);
- images->width = MAX (images->width, w);
- images->height = MAX (images->height, h);
+ if (rest_pixbuf)
+ {
+ g_object_unref (rest_pixbuf);
+ }
+ g_list_foreach (list, (GFunc) g_object_unref, NULL);
STOP_PROFILER ("loading spinner animation")
+
+ return NULL;
}
static EphySpinnerCacheData *
@@ -310,11 +370,9 @@ ephy_spinner_cache_data_new (GdkScreen *screen)
data->screen = screen;
data->icon_theme = gtk_icon_theme_get_for_screen (screen);
g_signal_connect_swapped (data->icon_theme, "changed",
- G_CALLBACK (ephy_spinner_cache_data_load),
+ G_CALLBACK (ephy_spinner_cache_data_unload),
data);
- ephy_spinner_cache_data_load (data);
-
return data;
}
@@ -326,56 +384,17 @@ ephy_spinner_cache_data_free (EphySpinnerCacheData *data)
g_signal_handlers_disconnect_by_func
(data->icon_theme,
- G_CALLBACK (ephy_spinner_cache_data_load), data);
+ G_CALLBACK (ephy_spinner_cache_data_unload), data);
ephy_spinner_cache_data_unload (data);
g_free (data);
}
-static int
-compare_size (gconstpointer images_ptr,
- gconstpointer size_ptr)
-{
- const EphySpinnerImages *images = (const EphySpinnerImages *) images_ptr;
- GtkIconSize size = GPOINTER_TO_INT (size_ptr);
-
- if (images->size == size)
- {
- return 0;
- }
-
- return -1;
-}
-
-static GdkPixbuf *
-scale_to_size (GdkPixbuf *pixbuf,
- int dw,
- int dh)
-{
- GdkPixbuf *result;
- int pw, ph;
-
- pw = gdk_pixbuf_get_width (pixbuf);
- ph = gdk_pixbuf_get_height (pixbuf);
-
- if (pw != dw || ph != dh)
- {
- result = gdk_pixbuf_scale_simple (pixbuf, dw, dh,
- GDK_INTERP_BILINEAR);
- }
- else
- {
- result = g_object_ref (pixbuf);
- }
-
- return result;
-}
-
static EphySpinnerImages *
ephy_spinner_cache_get_images (EphySpinnerCache *cache,
GdkScreen *screen,
- GtkIconSize size)
+ GtkIconSize icon_size)
{
EphySpinnerCachePrivate *priv = cache->priv;
EphySpinnerCacheData *data;
@@ -385,7 +404,15 @@ ephy_spinner_cache_get_images (EphySpinnerCache *cache,
GList *element, *l;
int h, w;
- LOG ("Getting animation images at size %d for screen %p", size, screen);
+ LOG ("Getting animation images for screen %p at size %d", screen, icon_size);
+
+ g_return_val_if_fail (icon_size >= 0 && icon_size < LAST_ICON_SIZE, NULL);
+
+ /* Backward compat: "invalid" meant "native" size which doesn't exist anymore */
+ if (icon_size == GTK_ICON_SIZE_INVALID)
+ {
+ icon_size = GTK_ICON_SIZE_DIALOG;
+ }
data = g_hash_table_lookup (priv->hash, screen);
if (data == NULL)
@@ -394,51 +421,30 @@ ephy_spinner_cache_get_images (EphySpinnerCache *cache,
g_hash_table_insert (priv->hash, screen, data);
}
- if (data->images == NULL || data->originals == NULL)
+ images = data->images[icon_size];
+ if (images == EPHY_SPINNER_IMAGES_INVALID)
{
/* Load failed, but don't try endlessly again! */
return NULL;
}
- element = g_list_find_custom (data->images,
- GINT_TO_POINTER (size),
- (GCompareFunc) compare_size);
- if (element != NULL)
- {
- return ephy_spinner_images_copy ((EphySpinnerImages *) element->data);
- }
-
- settings = gtk_settings_get_for_screen (screen);
- if (!gtk_icon_size_lookup_for_settings (settings, size, &w, &h))
+ if (images != NULL)
{
- g_warning ("Failed to look up icon size\n");
- return NULL;
+ /* Return cached data */
+ return ephy_spinner_images_copy (images);
}
- images = g_new (EphySpinnerImages, 1);
- images->size = size;
- images->width = w;
- images->height = h;
- images->images = NULL;
-
- START_PROFILER ("scaling spinner animation")
+ images = ephy_spinner_images_load (screen, data->icon_theme, icon_size);
- for (l = data->originals->images; l != NULL; l = l->next)
+ if (images == NULL)
{
- pixbuf = (GdkPixbuf *) l->data;
- scaled_pixbuf = scale_to_size (pixbuf, w, h);
+ /* Mark as failed-to-load */
+ data->images[icon_size] = EPHY_SPINNER_IMAGES_INVALID;
- images->images = g_list_prepend (images->images, scaled_pixbuf);
+ return NULL;
}
- images->images = g_list_reverse (images->images);
-
- images->quiescent_pixbuf =
- scale_to_size (data->originals->quiescent_pixbuf, w, h);
- /* store in cache */
- data->images = g_list_prepend (data->images, images);
-
- STOP_PROFILER ("scaling spinner animation")
+ data->images[icon_size] = images;
return ephy_spinner_images_copy (images);
}
@@ -463,11 +469,11 @@ ephy_spinner_cache_finalize (GObject *object)
EphySpinnerCache *cache = EPHY_SPINNER_CACHE (object);
EphySpinnerCachePrivate *priv = cache->priv;
- LOG ("EphySpinnerCache finalising");
-
g_hash_table_destroy (priv->hash);
- G_OBJECT_CLASS (cache_parent_class)->finalize (object);
+ LOG ("EphySpinnerCache finalised");
+
+ G_OBJECT_CLASS (ephy_spinner_cache_parent_class)->finalize (object);
}
static void
@@ -475,7 +481,7 @@ ephy_spinner_cache_class_init (EphySpinnerCacheClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- cache_parent_class = g_type_class_peek_parent (klass);
+ ephy_spinner_cache_parent_class = g_type_class_peek_parent (klass);
object_class->finalize = ephy_spinner_cache_finalize;
@@ -498,10 +504,8 @@ ephy_spinner_cache_ref (void)
return spinner_cache;
}
- else
- {
- return g_object_ref (spinner_cache);
- }
+
+ return g_object_ref (spinner_cache);
}
/* Spinner implementation */
@@ -611,7 +615,7 @@ ephy_spinner_init (EphySpinner *spinner)
details = spinner->details = EPHY_SPINNER_GET_PRIVATE (spinner);
details->cache = ephy_spinner_cache_ref ();
- details->size = GTK_ICON_SIZE_INVALID;
+ details->size = GTK_ICON_SIZE_DIALOG;
details->spinning = FALSE;
details->timeout = SPINNER_TIMEOUT;
}
@@ -800,13 +804,17 @@ ephy_spinner_stop (EphySpinner *spinner)
* @spinner: a #EphySpinner
* @size: the size of type %GtkIconSize
*
- * Set the size of the spinner. Use %GTK_ICON_SIZE_INVALID to use the
- * native size of the icons.
+ * Set the size of the spinner.
**/
void
ephy_spinner_set_size (EphySpinner *spinner,
GtkIconSize size)
{
+ if (size == GTK_ICON_SIZE_INVALID)
+ {
+ size = GTK_ICON_SIZE_DIALOG;
+ }
+
if (size != spinner->details->size)
{
ephy_spinner_unload_images (spinner);
@@ -867,8 +875,8 @@ ephy_spinner_size_request (GtkWidget *widget,
/* allocate some extra margin so we don't butt up against toolbar edges */
if (spinner->details->size != GTK_ICON_SIZE_MENU)
{
- requisition->width += 4;
- requisition->height += 4;
+ requisition->width += 2;
+ requisition->height += 2;
}
}
diff --git a/lib/widgets/testspinner.c b/lib/widgets/testspinner.c
index 7ed4d3c52..46eca658c 100644
--- a/lib/widgets/testspinner.c
+++ b/lib/widgets/testspinner.c
@@ -22,7 +22,7 @@
#include <gtk/gtk.h>
#define COMPILING_TESTSPINNER
-#define LOG(msg, args...) G_STMT_START { } G_STMT_END
+#define LOG(msg, args...) g_print(msg, ## args); g_print ("\n")
#define START_PROFILER(name)
#define STOP_PROFILER(name)