diff options
author | Matthias Clasen <matthiasc@src.gnome.org> | 2004-07-17 03:55:07 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2004-07-17 03:55:07 +0000 |
commit | a5638e82e8f5bef394166fecd997752204299155 (patch) | |
tree | cd6d74fceba6a917d1f5b9ffdef1329ce01fd06c /gtk | |
parent | 1d45cbd83155e4df2bbbf61230ea4f09bb44dde6 (diff) | |
download | gtk+-a5638e82e8f5bef394166fecd997752204299155.tar.gz |
Support named themed window icons.
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/gtkicontheme.c | 73 | ||||
-rw-r--r-- | gtk/gtkicontheme.h | 2 | ||||
-rw-r--r-- | gtk/gtkwindow.c | 243 | ||||
-rw-r--r-- | gtk/gtkwindow.h | 5 |
4 files changed, 319 insertions, 4 deletions
diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c index c4b30f3672..ef04e1c111 100644 --- a/gtk/gtkicontheme.c +++ b/gtk/gtkicontheme.c @@ -1295,6 +1295,77 @@ gtk_icon_theme_has_icon (GtkIconTheme *icon_theme, return FALSE; } +static void +add_size (gpointer key, + gpointer value, + gpointer user_data) +{ + gint **res_p = user_data; + + **res_p = GPOINTER_TO_INT (key); + + *res_p++; +} + +/** + * gtk_icon_theme_get_icon_sizes: + * @icon_theme: a #GtkIconTheme + * @icon_name: the name of an icon + * + * Returns an array of integers describing the sizes at which + * the icon is available without scaling. A size of -1 means + * that the icon is available in a scalable format. The array + * is zero-terminated. + * + * Return value: An newly allocated array describing the sizes at + * which the icon is available. + * + * Since: 2.6 + **/ +gint * +gtk_icon_theme_get_icon_sizes (GtkIconTheme *icon_theme, + const char *icon_name) +{ + GList *l, *d; + GHashTable *sizes; + gint *result; + guint suffix; + + GtkIconThemePrivate *priv; + + g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), FALSE); + + priv = icon_theme->priv; + + ensure_valid_themes (icon_theme); + + sizes = g_hash_table_new (g_direct_hash, g_direct_equal); + + for (l = priv->themes; l; l = l->next) + { + IconTheme *theme = l->data; + for (d = theme->dirs; d; d = d->next) + { + IconThemeDir *dir = d->data; + + suffix = GPOINTER_TO_UINT (g_hash_table_lookup (dir->icons, icon_name)); + if (suffix != ICON_SUFFIX_NONE) + { + if (suffix == ICON_SUFFIX_SVG) + g_hash_table_insert (sizes, GINT_TO_POINTER (-1), NULL); + else + g_hash_table_insert (sizes, GINT_TO_POINTER (dir->size), NULL); + } + } + } + + result = g_new0 (gint, g_hash_table_size (sizes) + 1); + + g_hash_table_foreach (sizes, add_size, &result); + g_hash_table_destroy (sizes); + + return result; +} static void add_key_to_hash (gpointer key, @@ -2275,7 +2346,7 @@ icon_info_ensure_scale_and_pixbuf (GtkIconInfo *icon_info, * * Renders an icon previously looked up in an icon theme using * gtk_icon_theme_lookup_icon(); the size will be based on the size - * pssed to gtk_icon_theme_lookup_icon(). Note that the resulting + * passed to gtk_icon_theme_lookup_icon(). Note that the resulting * pixbuf may not be exactly this size; an icon theme may have icons * that differ slightly from their nominal sizes, and in addition GTK+ * will avoid scaling icons that it considers sufficiently close to the diff --git a/gtk/gtkicontheme.h b/gtk/gtkicontheme.h index 33bd6625fa..c97d7a1305 100644 --- a/gtk/gtkicontheme.h +++ b/gtk/gtkicontheme.h @@ -116,6 +116,8 @@ void gtk_icon_theme_set_custom_theme (GtkIconTheme gboolean gtk_icon_theme_has_icon (GtkIconTheme *icon_theme, const gchar *icon_name); +gint *gtk_icon_theme_get_icon_sizes (GtkIconTheme *icon_theme, + const gchar *icon_name); GtkIconInfo * gtk_icon_theme_lookup_icon (GtkIconTheme *icon_theme, const gchar *icon_name, gint size, diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 9ffe43b7e6..a6b9c30bf9 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -38,6 +38,7 @@ #include "gtkkeyhash.h" #include "gtkmain.h" #include "gtkiconfactory.h" +#include "gtkicontheme.h" #include "gtkintl.h" #include "gtkmarshalers.h" #include "gtkplug.h" @@ -70,6 +71,7 @@ enum { PROP_DEFAULT_HEIGHT, PROP_DESTROY_WITH_PARENT, PROP_ICON, + PROP_ICON_NAME, PROP_SCREEN, PROP_TYPE_HINT, PROP_SKIP_TASKBAR_HINT, @@ -91,9 +93,11 @@ typedef struct GList *icon_list; GdkPixmap *icon_pixmap; GdkPixmap *icon_mask; + gchar *icon_name; guint realized : 1; guint using_default_icon : 1; guint using_parent_icon : 1; + guint using_themed_icon : 1; } GtkWindowIconInfo; typedef struct { @@ -261,6 +265,10 @@ static void gtk_window_set_default_size_internal (GtkWindow *window, gint height, gboolean is_geometry); +static void update_themed_icon (GtkIconTheme *theme, + GtkWindow *window); +static GList *icon_list_from_theme (GtkWidget *widget, + const gchar *name); static void gtk_window_realize_icon (GtkWindow *window); static void gtk_window_unrealize_icon (GtkWindow *window); @@ -273,6 +281,7 @@ static GHashTable *mnemonic_hash_table = NULL; static GtkBinClass *parent_class = NULL; static guint window_signals[LAST_SIGNAL] = { 0 }; static GList *default_icon_list = NULL; +static gchar *default_icon_name = NULL; static guint default_icon_serial = 0; static gboolean disable_startup_notification = FALSE; static gboolean sent_startup_notification = FALSE; @@ -539,6 +548,22 @@ gtk_window_class_init (GtkWindowClass *klass) GDK_TYPE_PIXBUF, G_PARAM_READWRITE)); + /** + * GtkWindow:icon-name: + * + * The :icon-name property specifies the name of the themed icon to + * use as the window icon. See #GtkIconTheme for more details. + * + * Since: 2.6 + */ + g_object_class_install_property (gobject_class, + PROP_ICON_NAME, + g_param_spec_string ("icon_name", + P_("Icon Name"), + P_("Name of the themed icon for this window"), + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_SCREEN, g_param_spec_object ("screen", @@ -858,6 +883,9 @@ gtk_window_set_property (GObject *object, gtk_window_set_icon (window, g_value_get_object (value)); break; + case PROP_ICON_NAME: + gtk_window_set_icon_name (window, g_value_get_string (value)); + break; case PROP_SCREEN: gtk_window_set_screen (window, g_value_get_object (value)); break; @@ -949,6 +977,9 @@ gtk_window_get_property (GObject *object, case PROP_ICON: g_value_set_object (value, gtk_window_get_icon (window)); break; + case PROP_ICON_NAME: + g_value_set_string (value, gtk_window_get_icon_name (window)); + break; case PROP_SCREEN: g_value_set_object (value, window->screen); break; @@ -2430,6 +2461,14 @@ get_icon_info (GtkWindow *window) "gtk-window-icon-info"); } +static void +free_icon_info (GtkWindowIconInfo *info) +{ + g_free (info->icon_name); + g_free (info); +} + + static GtkWindowIconInfo* ensure_icon_info (GtkWindow *window) { @@ -2443,7 +2482,7 @@ ensure_icon_info (GtkWindow *window) g_object_set_data_full (G_OBJECT (window), "gtk-window-icon-info", info, - g_free); + (GDestroyNotify)free_icon_info); } return info; @@ -2599,13 +2638,50 @@ get_pixmap_and_mask (GdkWindow *window, } } +static GList * +icon_list_from_theme (GtkWidget *widget, + const gchar *name) +{ + GList *list; + + GtkIconTheme *icon_theme; + GdkPixbuf *icon; + gint *sizes; + gint i; + + icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget)); + + sizes = gtk_icon_theme_get_icon_sizes (icon_theme, name); + list = NULL; + + for (i = 0; sizes[i]; i++) + { + /* FIXME + * We need an EWMH extension to handle scalable icons + * by passing their name to the WM. For now just use a + * fixed size of 48. + */ + if (sizes[i] == -1) + icon = gtk_icon_theme_load_icon (icon_theme, name, + 48, 0, NULL); + else + icon = gtk_icon_theme_load_icon (icon_theme, name, + sizes[i], 0, NULL); + if (icon) + list = g_list_append (list, icon); + } + + return list; +} + + static void gtk_window_realize_icon (GtkWindow *window) { GtkWidget *widget; GtkWindowIconInfo *info; GList *icon_list; - + widget = GTK_WIDGET (window); g_return_if_fail (widget->window != NULL); @@ -2626,9 +2702,17 @@ gtk_window_realize_icon (GtkWindow *window) info->using_default_icon = FALSE; info->using_parent_icon = FALSE; + info->using_themed_icon = FALSE; icon_list = info->icon_list; - + + /* Look up themed icon */ + if (icon_list == NULL && info->icon_name) + { + icon_list = icon_list_from_theme (widget, info->icon_name); + info->using_themed_icon = TRUE; + } + /* Inherit from transient parent */ if (icon_list == NULL && window->transient_parent) { @@ -2644,6 +2728,14 @@ gtk_window_realize_icon (GtkWindow *window) if (icon_list) info->using_default_icon = TRUE; } + + /* Look up themed icon */ + if (icon_list == NULL && default_icon_name) + { + icon_list = icon_list_from_theme (widget, default_icon_name); + info->using_default_icon = TRUE; + info->using_themed_icon = TRUE; + } gdk_window_set_icon_list (widget->window, icon_list); @@ -2663,6 +2755,18 @@ gtk_window_realize_icon (GtkWindow *window) info->icon_mask); info->realized = TRUE; + + if (info->using_themed_icon) + { + GtkIconTheme *icon_theme; + + g_list_foreach (icon_list, (GFunc) g_object_unref, NULL); + g_list_free (icon_list); + + icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window))); + g_signal_connect (icon_theme, "changed", + G_CALLBACK (update_themed_icon), window); + } } static void @@ -2687,11 +2791,21 @@ gtk_window_unrealize_icon (GtkWindow *window) info->icon_pixmap = NULL; info->icon_mask = NULL; + if (info->using_themed_icon) + { + GtkIconTheme *icon_theme; + + icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window))); + + g_signal_handlers_disconnect_by_func (icon_theme, update_themed_icon, window); + } + /* We don't clear the properties on the window, just figure the * window is going away. */ info->realized = FALSE; + } /** @@ -2826,6 +2940,79 @@ gtk_window_set_icon (GtkWindow *window, g_list_free (list); } + +static void +update_themed_icon (GtkIconTheme *icon_theme, + GtkWindow *window) +{ + g_object_notify (G_OBJECT (window), "icon"); + + gtk_window_unrealize_icon (window); + + if (GTK_WIDGET_REALIZED (window)) + gtk_window_realize_icon (window); +} + +/** + * gtk_window_set_icon_name: + * @window: a #GtkWindow + * @name: the name of the themed icon + * + * Sets the icon for the window from a named themed icon. See + * the docs for #GtkIconTheme for more details. + * + * Note that this has nothing to do with the WM_ICON_NAME + * property which is mentioned in the ICCCM. + * + * Since: 2.6 + */ +void +gtk_window_set_icon_name (GtkWindow *window, + const gchar *name) +{ + GtkWindowIconInfo *info; + gchar *tmp; + + g_return_if_fail (GTK_IS_WINDOW (window)); + + info = ensure_icon_info (window); + + tmp = info->icon_name; + info->icon_name = g_strdup (name); + g_free (tmp); + + g_list_foreach (info->icon_list, (GFunc) g_object_unref, NULL); + g_list_free (info->icon_list); + + update_themed_icon (NULL, window); + + g_object_notify (G_OBJECT (window), "icon_name"); +} + +/** + * gtk_window_get_icon_name: + * @window: a #GtkWindow + * + * Returns the name of the themed icon for the window, + * see gtk_window_set_icon_name(). + * + * Returns: the icon name or %NULL if the window has + * no themed icon + * + * Since: 2.6 + */ +G_CONST_RETURN gchar * +gtk_window_get_icon_name (GtkWindow *window) +{ + GtkWindowIconInfo *info; + + g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); + + info = ensure_icon_info (window); + + return info->icon_name; +} + /** * gtk_window_get_icon: * @window: a #GtkWindow @@ -2986,6 +3173,56 @@ gtk_window_set_default_icon (GdkPixbuf *icon) } /** + * gtk_window_set_default_icon_name: + * @name: the name of the themed icon + * + * Sets an icon to be used as fallback for windows that haven't + * had gtk_window_set_icon_list() called on them from a named + * themed icon, see gtk_window_set_icon_name(). + * + * Since: 2.6 + **/ +void +gtk_window_set_default_icon_name (const gchar *name) +{ + GList *tmp_list; + GList *toplevels; + + /* Update serial so we don't used cached pixmaps/masks + */ + default_icon_serial++; + + g_free (default_icon_name); + default_icon_name = g_strdup (name); + + g_list_foreach (default_icon_list, + (GFunc) g_object_unref, NULL); + + g_list_free (default_icon_list); + default_icon_list = NULL; + + /* Update all toplevels */ + toplevels = gtk_window_list_toplevels (); + tmp_list = toplevels; + while (tmp_list != NULL) + { + GtkWindowIconInfo *info; + GtkWindow *w = tmp_list->data; + + info = get_icon_info (w); + if (info && info->using_default_icon && info->using_themed_icon) + { + gtk_window_unrealize_icon (w); + if (GTK_WIDGET_REALIZED (w)) + gtk_window_realize_icon (w); + } + + tmp_list = tmp_list->next; + } + g_list_free (toplevels); +} + +/** * gtk_window_set_default_icon_from_file: * @filename: location of icon file * @err: location to store error, or %NULL. diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index bcf6963e00..a52d675c0a 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -257,13 +257,18 @@ void gtk_window_set_icon_list (GtkWindow *window, GList* gtk_window_get_icon_list (GtkWindow *window); void gtk_window_set_icon (GtkWindow *window, GdkPixbuf *icon); +void gtk_window_set_icon_name (GtkWindow *window, + const gchar *name); gboolean gtk_window_set_icon_from_file (GtkWindow *window, const gchar *filename, GError **err); GdkPixbuf* gtk_window_get_icon (GtkWindow *window); +G_CONST_RETURN +gchar *gtk_window_get_icon_name (GtkWindow *window); void gtk_window_set_default_icon_list (GList *list); GList* gtk_window_get_default_icon_list (void); void gtk_window_set_default_icon (GdkPixbuf *icon); +void gtk_window_set_default_icon_name (const gchar *name); gboolean gtk_window_set_default_icon_from_file (const gchar *filename, GError **err); |