Support named themed window icons.

This commit is contained in:
Matthias Clasen 2004-07-17 03:55:07 +00:00
parent 1d45cbd831
commit a5638e82e8
10 changed files with 400 additions and 4 deletions

View File

@ -1,3 +1,21 @@
Fri Jul 16 23:20:34 2004 Matthias Clasen <maclas@gmx.de>
Support themed window icons. (#92346, Calum Benson)
* gtk/gtkicontheme.c (gtk_icon_theme_get_icon_sizes): New
function to obtain information about the sizes in which an
icon is available.
* gtk/gtkwindow.h:
* gtk/gtkwindow.c (gtk_window_class_init):
(gtk_window_set_icon_name):
(gtk_window_get_icon_name): Add an "icon_name" property
(gtk_window_set_default_icon_name): ...and a default icon name.
(icon_list_from_theme):
(update_themed_icon): New auxiliary functions to create a
list of all available sizes of a themed icon and update the
window icon list from it.
2004-07-16 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkcombobox.c (gtk_combo_box_scroll_event): Make

View File

@ -1,3 +1,21 @@
Fri Jul 16 23:20:34 2004 Matthias Clasen <maclas@gmx.de>
Support themed window icons. (#92346, Calum Benson)
* gtk/gtkicontheme.c (gtk_icon_theme_get_icon_sizes): New
function to obtain information about the sizes in which an
icon is available.
* gtk/gtkwindow.h:
* gtk/gtkwindow.c (gtk_window_class_init):
(gtk_window_set_icon_name):
(gtk_window_get_icon_name): Add an "icon_name" property
(gtk_window_set_default_icon_name): ...and a default icon name.
(icon_list_from_theme):
(update_themed_icon): New auxiliary functions to create a
list of all available sizes of a themed icon and update the
window icon list from it.
2004-07-16 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkcombobox.c (gtk_combo_box_scroll_event): Make

View File

@ -1,3 +1,21 @@
Fri Jul 16 23:20:34 2004 Matthias Clasen <maclas@gmx.de>
Support themed window icons. (#92346, Calum Benson)
* gtk/gtkicontheme.c (gtk_icon_theme_get_icon_sizes): New
function to obtain information about the sizes in which an
icon is available.
* gtk/gtkwindow.h:
* gtk/gtkwindow.c (gtk_window_class_init):
(gtk_window_set_icon_name):
(gtk_window_get_icon_name): Add an "icon_name" property
(gtk_window_set_default_icon_name): ...and a default icon name.
(icon_list_from_theme):
(update_themed_icon): New auxiliary functions to create a
list of all available sizes of a themed icon and update the
window icon list from it.
2004-07-16 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkcombobox.c (gtk_combo_box_scroll_event): Make

View File

@ -1,3 +1,21 @@
Fri Jul 16 23:20:34 2004 Matthias Clasen <maclas@gmx.de>
Support themed window icons. (#92346, Calum Benson)
* gtk/gtkicontheme.c (gtk_icon_theme_get_icon_sizes): New
function to obtain information about the sizes in which an
icon is available.
* gtk/gtkwindow.h:
* gtk/gtkwindow.c (gtk_window_class_init):
(gtk_window_set_icon_name):
(gtk_window_get_icon_name): Add an "icon_name" property
(gtk_window_set_default_icon_name): ...and a default icon name.
(icon_list_from_theme):
(update_themed_icon): New auxiliary functions to create a
list of all available sizes of a themed icon and update the
window icon list from it.
2004-07-16 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkcombobox.c (gtk_combo_box_scroll_event): Make

View File

@ -1,3 +1,8 @@
Fri Jul 16 23:54:18 2004 Matthias Clasen <maclas@gmx.de>
* gtk/gtk-sections.txt: Add new GtkWindow and GtkIconTheme
functions for named themed window icons.
2004-07-16 Matthias Clasen <mclasen@redhat.com>
* gtk/gtk-sections.txt:

View File

@ -4559,6 +4559,7 @@ gtk_window_get_frame_dimensions
gtk_window_get_has_frame
gtk_window_get_icon
gtk_window_get_icon_list
gtk_window_get_icon_name
gtk_window_get_mnemonic_modifier
gtk_window_get_modal
gtk_window_get_position
@ -4578,9 +4579,11 @@ gtk_window_resize
gtk_window_set_default_icon_list
gtk_window_set_default_icon
gtk_window_set_default_icon_from_file
gtk_window_set_default_icon_name
gtk_window_set_icon
gtk_window_set_icon_list
gtk_window_set_icon_from_file
gtk_window_set_icon_name
gtk_window_set_auto_startup_notification
<SUBSECTION Standard>
GTK_WINDOW
@ -5308,6 +5311,7 @@ gtk_icon_theme_has_icon
gtk_icon_theme_lookup_icon
gtk_icon_theme_load_icon
gtk_icon_theme_list_icons
gtk_icon_theme_get_icon_sizes
gtk_icon_theme_get_example_icon_name
gtk_icon_theme_rescan_if_needed
gtk_icon_theme_add_builtin_icon

View File

@ -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

View File

@ -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,

View File

@ -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
@ -2985,6 +3172,56 @@ gtk_window_set_default_icon (GdkPixbuf *icon)
g_list_free (list);
}
/**
* 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

View File

@ -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);