guint use_fallback : 1;
guint force_scale_pixbuf : 1;
guint texture_is_symbolic : 1;
- guint preloaded : 1;
GtkWidget *owner;
GtkCssNode *node;
return paintable;
}
-/* We are calling this from css-validate, and the mapped state is not yet set, so
- * we have to calculate ahead of time if a widget will be mapped. */
-static gboolean
-will_be_mapped (GtkWidget *widget)
-{
- while (widget)
- {
- if (!_gtk_widget_get_visible (widget) ||
- !_gtk_widget_get_child_visible (widget))
- return FALSE;
- widget = _gtk_widget_get_parent (widget);
- }
-
- return TRUE;
-}
-
-void
-_gtk_icon_helper_preload (GtkIconHelper *self)
-{
- GtkIconTheme *icon_theme;
- GtkIconLookupFlags flags = 0;
- int size, scale;
- GtkCssStyle *style;
- GIcon *gicon = NULL;
- GIcon *free_gicon = NULL;
-
- /* Avoid constantly preloading as it may cause issues if we're trashing the icon cache */
- if (self->preloaded)
- return;
-
- self->preloaded = TRUE;
-
- switch (gtk_image_definition_get_storage_type (self->def))
- {
- case GTK_IMAGE_ICON_NAME:
- if (self->use_fallback)
- free_gicon = g_themed_icon_new_with_default_fallbacks (gtk_image_definition_get_icon_name (self->def));
- else
- free_gicon = g_themed_icon_new (gtk_image_definition_get_icon_name (self->def));
- gicon = free_gicon;
- break;
- case GTK_IMAGE_GICON:
- gicon = gtk_image_definition_get_gicon (self->def) ;
- break;
- case GTK_IMAGE_EMPTY:
- case GTK_IMAGE_PAINTABLE:
- default:
- break;
- }
-
- if (gicon && G_IS_THEMED_ICON (gicon))
- {
- int priority;
- style = gtk_css_node_get_style (self->node);
- icon_theme = gtk_css_icon_theme_value_get_icon_theme
- (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_ICON_THEME));
- flags |= get_icon_lookup_flags (self, style,
- gtk_widget_get_direction (self->owner));
- size = gtk_icon_helper_get_size (self);
- scale = gtk_widget_get_scale_factor (self->owner);
-
- /* Icons for widgets are visible have higher priority so they are loaded first */
- if (will_be_mapped (self->owner))
- priority = G_PRIORITY_DEFAULT;
- else
- priority = G_PRIORITY_DEFAULT + 1;
-
- gtk_icon_theme_choose_icon_async (icon_theme,
- (const gchar **)g_themed_icon_get_names (G_THEMED_ICON (gicon)),
- size, scale,
- flags, priority, NULL, NULL, NULL);
- }
-
- if (free_gicon)
- g_object_unref (free_gicon);
-}
-
static void
gtk_icon_helper_ensure_paintable (GtkIconHelper *self)
{
const gchar *icon_name);
void _gtk_icon_helper_set_paintable (GtkIconHelper *self,
GdkPaintable *paintable);
-void _gtk_icon_helper_preload (GtkIconHelper *self);
gboolean _gtk_icon_helper_set_pixel_size (GtkIconHelper *self,
gint pixel_size);
g_mutex_lock (&self->ref->lock);
}
-static gboolean
-gtk_icon_theme_trylock (GtkIconTheme *self)
-{
- return g_mutex_trylock (&self->ref->lock);
-}
-
static void
gtk_icon_theme_unlock (GtkIconTheme *self)
{
return icon;
}
-typedef struct {
- char **icon_names;
- int size;
- int scale;
- GtkIconLookupFlags flags;
-} ChooseIconData;
-
-static ChooseIconData *
-choose_icon_data_new (const char *icon_names[],
- int size,
- int scale,
- GtkIconLookupFlags flags)
-{
- ChooseIconData *data = g_new0 (ChooseIconData, 1);
- data->icon_names = g_strdupv ((char **)icon_names);
- data->size = size;
- data->scale = scale;
- data->flags = flags;
- return data;
-}
-
-static void
-choose_icon_data_free (ChooseIconData *data)
-{
- g_strfreev (data->icon_names);
- g_free (data);
-}
-
-static void
-choose_icon_thread (GTask *task,
- gpointer source_object,
- gpointer task_data,
- GCancellable *cancellable)
-{
- ChooseIconData *data = task_data;
- GtkIconTheme *self = GTK_ICON_THEME (source_object);
- GtkIcon *icon;
-
- icon = gtk_icon_theme_choose_icon (self,
- (const char **)data->icon_names,
- data->size,
- data->scale,
- data->flags);
-
- if (icon)
- {
- g_mutex_lock (&icon->texture_lock);
- (void)icon_ensure_scale_and_texture__locked (icon, TRUE);
-
- if (icon->texture)
- g_task_return_pointer (task, g_object_ref (icon), g_object_unref);
- else if (icon->load_error)
- g_task_return_error (task, g_error_copy (icon->load_error));
- else
- g_task_return_new_error (task,
- GTK_ICON_THEME_ERROR, GTK_ICON_THEME_NOT_FOUND,
- _("Icon not present in theme %s"), self->current_theme);
-
- g_mutex_unlock (&icon->texture_lock);
- }
- else
- g_task_return_new_error (task,
- GTK_ICON_THEME_ERROR, GTK_ICON_THEME_NOT_FOUND,
- _("Icon not present in theme %s"), self->current_theme);
-}
-
-static void
-load_icon_thread (GTask *task,
- gpointer source_object,
- gpointer task_data,
- GCancellable *cancellable)
-{
- GtkIcon *icon = task_data;
-
- g_mutex_lock (&icon->texture_lock);
- (void)icon_ensure_scale_and_texture__locked (icon, TRUE);
- g_mutex_unlock (&icon->texture_lock);
- g_task_return_pointer (task, g_object_ref (icon), g_object_unref);
-}
-
-/**
- * gtk_icon_theme_choose_icon_async:
- * @self: a #GtkIconTheme
- * @icon_names: (array zero-terminated=1): %NULL-terminated array of
- * icon names to lookup
- * @size: desired icon size.
- * @scale: the window scale this will be displayed on
- * @flags: flags modifying the behavior of the icon lookup
- * @io_priority: the [I/O priority][io-priority] of the request.
- * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore
- * @callback: (scope async): a #GAsyncReadyCallback to call when the
- * request is satisfied
- * @user_data: (closure): the data to pass to callback function
- *
- * Asynchronously lookup, load, render and scale an icon .
- *
- * For more details, see gtk_icon_theme_choose_icon() which is the synchronous
- * version of this call.
- */
-void
-gtk_icon_theme_choose_icon_async (GtkIconTheme *self,
- const gchar *icon_names[],
- gint size,
- gint scale,
- GtkIconLookupFlags flags,
- int priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GTask *task;
- GtkIcon *icon = NULL;
- gboolean would_block = FALSE;
-
- g_return_if_fail (GTK_IS_ICON_THEME (self));
- g_return_if_fail (icon_names != NULL);
- g_return_if_fail ((flags & GTK_ICON_LOOKUP_NO_SVG) == 0 ||
- (flags & GTK_ICON_LOOKUP_FORCE_SVG) == 0);
- g_warn_if_fail ((flags & GTK_ICON_LOOKUP_GENERIC_FALLBACK) == 0);
-
- task = g_task_new (self, cancellable, callback, user_data);
- g_task_set_priority (task, priority);
-
- if (gtk_icon_theme_trylock (self))
- {
- icon = choose_icon (self, icon_names, size, scale, flags, TRUE, &would_block);
- gtk_icon_theme_unlock (self);
- }
- else
- would_block = TRUE;
-
- if (icon == NULL)
- {
- if (would_block)
- {
- /* Don't have valid theme data, do everything in a thread */
- g_task_set_task_data (task, choose_icon_data_new (icon_names, size, scale, flags), (GDestroyNotify)choose_icon_data_free);
- g_task_run_in_thread (task, choose_icon_thread);
- }
- else
- {
- g_task_return_new_error (task,
- GTK_ICON_THEME_ERROR, GTK_ICON_THEME_NOT_FOUND,
- _("Icon not present in theme %s"), self->current_theme);
- }
- }
- else
- {
- gboolean done = FALSE;
- if (g_mutex_trylock (&icon->texture_lock))
- {
- if (icon->texture)
- {
- done = TRUE;
- g_task_return_pointer (task, icon, g_object_unref);
- }
- else if (icon->load_error)
- {
- done = TRUE;
- g_task_return_error (task, g_error_copy (icon->load_error));
- g_object_unref (icon);
- }
- g_mutex_unlock (&icon->texture_lock);
- }
-
- if (!done)
- {
- /* Not here, load it in a thread */
- g_task_set_task_data (task, icon, g_object_unref);
- g_task_run_in_thread (task, load_icon_thread);
- }
- }
-}
-
-/**
- * gtk_icon_theme_choose_icon_finish:
- * @self: a #GtkIconTheme
- * @result: a #GAsyncResult
- * @error: (allow-none): location to store error information on failure,
- * or %NULL.
- *
- * Finishes an async icon load, see gtk_icon_theme_choose_icon_async().
- *
- * Returns: (transfer full): the rendered icon; this may be a newly
- * created icon or a new reference to an internal icon, so you must
- * not modify the icon. Use g_object_unref() to release your reference
- * to the icon.
- */
-GtkIcon *
-gtk_icon_theme_choose_icon_finish (GtkIconTheme *self,
- GAsyncResult *result,
- GError **error)
-{
- GTask *task = G_TASK (result);
-
- g_return_val_if_fail (g_task_is_valid (result, self), NULL);
-
- return g_task_propagate_pointer (task, error);
-}
-
/* Error quark */
GQuark
gtk_icon_theme_error_quark (void)
gint scale,
GtkIconLookupFlags flags);
GDK_AVAILABLE_IN_ALL
-void gtk_icon_theme_choose_icon_async (GtkIconTheme *self,
- const gchar *icon_names[],
- gint size,
- gint scale,
- GtkIconLookupFlags flags,
- int priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GDK_AVAILABLE_IN_ALL
-GtkIcon * gtk_icon_theme_choose_icon_finish (GtkIconTheme *self,
- GAsyncResult *result,
- GError **error);
-GDK_AVAILABLE_IN_ALL
GtkIcon * gtk_icon_theme_lookup_by_gicon (GtkIconTheme *self,
GIcon *icon,
gint size,
GTK_WIDGET_CLASS (gtk_image_parent_class)->style_updated (widget);
- _gtk_icon_helper_preload (priv->icon_helper);
-
priv->baseline_align = 0.0;
}
"usage: test-icon-theme list <theme name> [context]\n"
" or\n"
"usage: test-icon-theme display <theme name> <icon name> [size] [scale]\n"
- " or\n"
- "usage: test-icon-theme display-async <theme name> <icon name> [size] [scale]\n"
);
}
-static void
-icon_loaded_cb (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data)
-{
- GtkIcon *icon;
- GError *error;
-
- error = NULL;
- icon = gtk_icon_theme_choose_icon_finish (GTK_ICON_THEME (source_object),
- res, &error);
-
- if (icon == NULL)
- {
- g_print ("%s\n", error->message);
- exit (1);
- }
-
- gtk_image_set_from_paintable (GTK_IMAGE (user_data), GDK_PAINTABLE (icon));
- g_object_unref (icon);
-}
-
int
main (int argc, char *argv[])
{
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_widget_show (window);
- gtk_main ();
- }
- else if (strcmp (argv[1], "display-async") == 0)
- {
- GtkWidget *window, *image;
- const char *icons[2] = { NULL, NULL };
-
- if (argc < 4)
- {
- g_object_unref (icon_theme);
- usage ();
- return 1;
- }
-
- if (argc >= 5)
- size = atoi (argv[4]);
-
- if (argc >= 6)
- scale = atoi (argv[5]);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- image = gtk_image_new ();
- gtk_container_add (GTK_CONTAINER (window), image);
- g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
- gtk_widget_show (window);
-
- icons[0] = argv[3];
- gtk_icon_theme_choose_icon_async (icon_theme, icons, size, scale, flags, 0, NULL, icon_loaded_cb, image);
-
gtk_main ();
}
else if (strcmp (argv[1], "list") == 0)
g_list_free_full (icons, g_free);
}
-static gint loaded;
-
-static void
-load_icon (GObject *source,
- GAsyncResult *res,
- gpointer data)
-{
- GMainLoop *loop = data;
- GtkIconTheme *theme = GTK_ICON_THEME (source);
- GError *error = NULL;
- GtkIcon *icon;
-
- icon = gtk_icon_theme_choose_icon_finish (theme, res, &error);
- g_assert (icon != NULL);
- g_assert_no_error (error);
- g_object_unref (icon);
-
- loaded++;
- if (loaded == 2)
- g_main_loop_quit (loop);
-}
-
-static void
-test_async (void)
-{
- GtkIconTheme *theme;
- GMainLoop *loop;
- const char *icons[] = { "twosize-fixed", NULL };
-
- loop = g_main_loop_new (NULL, FALSE);
-
- g_printerr ("test_async\n");
- theme = get_test_icontheme (TRUE);
- gtk_icon_theme_choose_icon_async (theme, icons, 32, 1, 0, 0, NULL, load_icon, loop);
- gtk_icon_theme_choose_icon_async (theme, icons, 48, 1, 0, 0, NULL, load_icon, loop);
-
- g_main_loop_run (loop);
- g_main_loop_unref (loop);
-
- g_assert (loaded == 2);
-}
-
static void
test_inherit (void)
{
g_test_add_func ("/icontheme/svg-size", test_svg_size);
g_test_add_func ("/icontheme/size", test_size);
g_test_add_func ("/icontheme/list", test_list);
- g_test_add_func ("/icontheme/async", test_async);
g_test_add_func ("/icontheme/inherit", test_inherit);
g_test_add_func ("/icontheme/nonsquare-symbolic", test_nonsquare_symbolic);