2003-07-02 22:44:09 +00:00
|
|
|
|
/* GtkIconTheme - a loader for icon themes
|
|
|
|
|
* gtk-icon-theme.c Copyright (C) 2002, 2003 Red Hat, Inc.
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2012-02-27 13:01:10 +00:00
|
|
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
2003-07-02 22:44:09 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2003-07-20 15:50:14 +00:00
|
|
|
|
#include "config.h"
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
2003-07-20 15:50:14 +00:00
|
|
|
|
#ifdef HAVE_UNISTD_H
|
2003-07-02 22:44:09 +00:00
|
|
|
|
#include <unistd.h>
|
2003-07-20 15:50:14 +00:00
|
|
|
|
#endif
|
2003-07-02 22:44:09 +00:00
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
2012-11-26 12:52:05 +00:00
|
|
|
|
#include <math.h>
|
2003-07-02 22:44:09 +00:00
|
|
|
|
#include <glib.h>
|
2004-12-12 21:09:13 +00:00
|
|
|
|
#include <glib/gstdio.h>
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2003-07-20 15:50:14 +00:00
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
#ifndef S_ISDIR
|
|
|
|
|
#define S_ISDIR(mode) ((mode)&_S_IFDIR)
|
|
|
|
|
#endif
|
2018-12-21 23:48:10 +00:00
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
2008-06-16 13:27:46 +00:00
|
|
|
|
#include <windows.h>
|
2018-12-21 23:48:10 +00:00
|
|
|
|
#include <shellapi.h>
|
2008-06-16 13:27:46 +00:00
|
|
|
|
#include "win32/gdkwin32.h"
|
2003-07-20 15:50:14 +00:00
|
|
|
|
#endif /* G_OS_WIN32 */
|
|
|
|
|
|
2016-01-14 17:53:50 +00:00
|
|
|
|
#include "gtkiconthemeprivate.h"
|
2015-12-02 23:33:51 +00:00
|
|
|
|
#include "gtkcsspalettevalueprivate.h"
|
2020-01-10 12:02:33 +00:00
|
|
|
|
#include "gtkcsscolorvalueprivate.h"
|
2010-09-18 23:57:32 +00:00
|
|
|
|
#include "gtkdebug.h"
|
2018-02-01 14:34:57 +00:00
|
|
|
|
#include "gtkiconcacheprivate.h"
|
2003-07-02 22:44:09 +00:00
|
|
|
|
#include "gtkintl.h"
|
2006-08-15 17:44:09 +00:00
|
|
|
|
#include "gtkmain.h"
|
2014-07-10 01:18:18 +00:00
|
|
|
|
#include "gtksettingsprivate.h"
|
2015-12-02 23:33:51 +00:00
|
|
|
|
#include "gtkstylecontextprivate.h"
|
2020-04-21 14:44:36 +00:00
|
|
|
|
#include "gtkstyleproviderprivate.h"
|
2003-07-20 15:50:14 +00:00
|
|
|
|
#include "gtkprivate.h"
|
2020-01-27 12:59:34 +00:00
|
|
|
|
#include "gtksnapshot.h"
|
2020-04-21 14:44:36 +00:00
|
|
|
|
#include "gtkwidgetprivate.h"
|
2016-01-29 22:27:35 +00:00
|
|
|
|
#include "gdkpixbufutilsprivate.h"
|
2019-08-29 15:07:45 +00:00
|
|
|
|
#include "gdk/gdktextureprivate.h"
|
2020-01-22 19:49:17 +00:00
|
|
|
|
#include "gdk/gdkprofilerprivate.h"
|
2011-11-08 13:15:30 +00:00
|
|
|
|
|
2020-07-03 02:21:07 +00:00
|
|
|
|
#define GDK_ARRAY_ELEMENT_TYPE char *
|
|
|
|
|
#define GDK_ARRAY_NULL_TERMINATED 1
|
|
|
|
|
#define GDK_ARRAY_FREE_FUNC g_free
|
|
|
|
|
#define GDK_ARRAY_TYPE_NAME GtkStrvBuilder
|
|
|
|
|
#define GDK_ARRAY_NAME gtk_strv_builder
|
|
|
|
|
#define GDK_ARRAY_PREALLOC 16
|
|
|
|
|
#include "gdk/gdkarrayimpl.c"
|
|
|
|
|
|
2011-04-14 21:07:29 +00:00
|
|
|
|
/**
|
|
|
|
|
* SECTION:gtkicontheme
|
|
|
|
|
* @Short_description: Looking up icons by name
|
|
|
|
|
* @Title: GtkIconTheme
|
|
|
|
|
*
|
|
|
|
|
* #GtkIconTheme provides a facility for looking up icons by name
|
|
|
|
|
* and size. The main reason for using a name rather than simply
|
|
|
|
|
* providing a filename is to allow different icons to be used
|
2014-02-04 23:10:11 +00:00
|
|
|
|
* depending on what “icon theme” is selected
|
2011-04-14 21:07:29 +00:00
|
|
|
|
* by the user. The operation of icon themes on Linux and Unix
|
2014-02-04 23:53:51 +00:00
|
|
|
|
* follows the [Icon Theme Specification](http://www.freedesktop.org/Standards/icon-theme-spec)
|
2014-06-22 20:46:11 +00:00
|
|
|
|
* There is a fallback icon theme, named `hicolor`, where applications
|
|
|
|
|
* should install their icons, but additional icon themes can be installed
|
|
|
|
|
* as operating system vendors and users choose.
|
2011-04-14 21:07:29 +00:00
|
|
|
|
*
|
|
|
|
|
* In many cases, named themes are used indirectly, via #GtkImage
|
2016-10-22 15:25:57 +00:00
|
|
|
|
* rather than directly, but looking up icons
|
2011-04-14 21:07:29 +00:00
|
|
|
|
* directly is also simple. The #GtkIconTheme object acts
|
|
|
|
|
* as a database of all the icons in the current theme. You
|
2014-02-07 18:01:26 +00:00
|
|
|
|
* can create new #GtkIconTheme objects, but it’s much more
|
2020-02-01 22:38:49 +00:00
|
|
|
|
* efficient to use the standard icon theme of the #GtkWidget
|
2011-04-14 21:07:29 +00:00
|
|
|
|
* so that the icon information is shared with other people
|
2014-06-22 20:46:11 +00:00
|
|
|
|
* looking up icons.
|
2014-01-27 19:55:18 +00:00
|
|
|
|
* |[<!-- language="C" -->
|
2011-04-14 21:07:29 +00:00
|
|
|
|
* GtkIconTheme *icon_theme;
|
2020-02-04 16:19:22 +00:00
|
|
|
|
* GtkIconPaintable *icon;
|
2020-02-05 16:08:29 +00:00
|
|
|
|
* GdkPaintable *paintable;
|
2011-04-14 21:07:29 +00:00
|
|
|
|
*
|
2020-02-01 22:38:49 +00:00
|
|
|
|
* icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (my_widget));
|
2020-01-30 09:44:12 +00:00
|
|
|
|
* icon = gtk_icon_theme_lookup_icon (icon_theme,
|
|
|
|
|
* "my-icon-name", // icon name
|
|
|
|
|
* 48, // icon size
|
|
|
|
|
* 1, // scale
|
|
|
|
|
* 0, // flags);
|
2020-02-05 16:08:29 +00:00
|
|
|
|
* paintable = GDK_PAINTABLE (icon);
|
|
|
|
|
* // Use the paintable
|
|
|
|
|
* g_object_unref (icon);
|
2014-01-27 17:12:55 +00:00
|
|
|
|
* ]|
|
2011-04-14 21:07:29 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
|
|
|
|
|
/* There are a lot of icon names (around 1000 in adwaita and 1000 in
|
|
|
|
|
* hicolor), and the are short, which makes individual allocations
|
|
|
|
|
* wasteful (i.e. glibc malloc min chunk size is 32 byte), so we and
|
|
|
|
|
* fragmenting. Instead we store the string in larger chunks of memory
|
|
|
|
|
* for the string data, avoiding duplicates via a hash.
|
|
|
|
|
*
|
|
|
|
|
* Additionally, doing a up-front hash lookup to intern an
|
|
|
|
|
* icon name allows further hash lookups (for each directory in
|
|
|
|
|
* the theme) to use g_direct_hash/equal() which makes those
|
|
|
|
|
* lookups faster.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
typedef struct _GtkStringSetChunk GtkStringSetChunk;
|
|
|
|
|
|
|
|
|
|
/* This size allows a malloc to be one page, including the next_chunk
|
|
|
|
|
pointer and the malloc overhead, which is a good size (one page) */
|
|
|
|
|
#define STRING_SET_CHUNK_SIZE (4096 - 2 *sizeof (gpointer))
|
|
|
|
|
|
|
|
|
|
struct _GtkStringSetChunk {
|
|
|
|
|
GtkStringSetChunk *next;
|
|
|
|
|
char data[STRING_SET_CHUNK_SIZE];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct _GtkStringSet {
|
|
|
|
|
GHashTable *hash;
|
|
|
|
|
GtkStringSetChunk *chunks;
|
|
|
|
|
int used_in_chunk;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_string_set_init (GtkStringSet *set)
|
|
|
|
|
{
|
|
|
|
|
set->hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
|
|
|
|
|
set->chunks = NULL;
|
|
|
|
|
set->used_in_chunk = STRING_SET_CHUNK_SIZE; /* To trigger a grow directly */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_string_set_destroy (GtkStringSet *set)
|
|
|
|
|
{
|
|
|
|
|
GtkStringSetChunk *next, *chunk;
|
|
|
|
|
g_hash_table_destroy (set->hash);
|
|
|
|
|
for (chunk = set->chunks; chunk != NULL; chunk = next)
|
|
|
|
|
{
|
|
|
|
|
next = chunk->next;
|
|
|
|
|
g_free (chunk);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
gtk_string_set_lookup (GtkStringSet *set,
|
|
|
|
|
const char *string)
|
|
|
|
|
{
|
|
|
|
|
return g_hash_table_lookup (set->hash, string);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_string_set_list (GtkStringSet *set,
|
|
|
|
|
GHashTable *result)
|
|
|
|
|
{
|
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
gpointer key;
|
|
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, set->hash);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, &key, NULL))
|
|
|
|
|
{
|
|
|
|
|
char *string = key;
|
|
|
|
|
g_hash_table_insert (result, string, string);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
gtk_string_set_add (GtkStringSet *set,
|
|
|
|
|
const char *string)
|
|
|
|
|
{
|
|
|
|
|
const char *intern = g_hash_table_lookup (set->hash, string);
|
|
|
|
|
|
|
|
|
|
if (intern == NULL)
|
|
|
|
|
{
|
|
|
|
|
GtkStringSetChunk *chunk;
|
|
|
|
|
int string_len = strlen (string) + 1;
|
|
|
|
|
|
|
|
|
|
if (string_len > STRING_SET_CHUNK_SIZE - set->used_in_chunk)
|
|
|
|
|
{
|
|
|
|
|
gsize chunk_size = sizeof (GtkStringSetChunk);
|
|
|
|
|
/* Doesn't fit in existing chunk, need a new one. Normally
|
|
|
|
|
* we allocate one of regular size, but in the case the
|
|
|
|
|
* string is longer than CHUNK_SIZE that we allocate enough
|
|
|
|
|
* for it to fit this one string. */
|
|
|
|
|
if (string_len > STRING_SET_CHUNK_SIZE)
|
|
|
|
|
chunk_size += string_len - STRING_SET_CHUNK_SIZE;
|
|
|
|
|
chunk = g_malloc (chunk_size);
|
|
|
|
|
chunk->next = set->chunks;
|
|
|
|
|
set->chunks = chunk;
|
|
|
|
|
set->used_in_chunk = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* We fit in existing chunk */
|
|
|
|
|
chunk = set->chunks;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intern = &chunk->data[set->used_in_chunk];
|
|
|
|
|
memcpy ((char *)intern, string, string_len);
|
|
|
|
|
set->used_in_chunk += string_len;
|
|
|
|
|
g_hash_table_insert (set->hash, (char *)intern, (char *)intern);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return intern;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
/* Threading:
|
|
|
|
|
*
|
|
|
|
|
* GtkIconTheme is partially threadsafe, construction and setup can
|
|
|
|
|
* only be done on the main thread (and this is not really fixable
|
|
|
|
|
* since it uses other things like GdkDisplay and GSettings and
|
|
|
|
|
* signals on those. However, once the icon theme is set up on the
|
|
|
|
|
* main thread we can pass it to a thread and do basic lookups on
|
|
|
|
|
* it. This will cause any parallel calls on the main thread (or any
|
|
|
|
|
* other thread) to block until its done, but most of the time
|
|
|
|
|
* lookups are fast. The only time its not fast is when we need
|
|
|
|
|
* to rescan the theme, but then it would be slow if we didn't block
|
|
|
|
|
* and did the rescan ourselves anyway.
|
|
|
|
|
*
|
|
|
|
|
* All private functions that take a GtkIconTheme (or one of its
|
|
|
|
|
* private data types (like IconThemeDir, UnthemedIcon, etc) arg are
|
|
|
|
|
* expected to be called with the icon theme lock held, unless the
|
2020-08-21 12:41:13 +00:00
|
|
|
|
* function has a _unlocked suffix. Any similar function that must be
|
2020-01-24 15:22:26 +00:00
|
|
|
|
* called on the main thread, will have a _mainthread suffix.
|
|
|
|
|
*
|
|
|
|
|
* So the rules for such functions are:
|
|
|
|
|
*
|
|
|
|
|
* * non-_unlocked function cannot call _unlocked functions.
|
|
|
|
|
* * _unlocked must lock before calling a non-_unlocked.
|
|
|
|
|
* * non-_mainthread cannot call _mainthread.
|
|
|
|
|
* * Public APIs must lock before calling a non-_unlocked private function
|
2020-01-29 10:08:02 +00:00
|
|
|
|
* * Public APIs that never call _mainthread are threadsafe.
|
2020-01-24 15:22:26 +00:00
|
|
|
|
*
|
2020-01-29 10:08:02 +00:00
|
|
|
|
* There is a global "icon_cache" G_LOCK, which protects icon_cache
|
|
|
|
|
* and lru_cache in GtkIconTheme as well as its reverse pointer
|
|
|
|
|
* GtkIcon->in_cache. This is sometimes taken with the theme lock held
|
2020-01-30 09:52:09 +00:00
|
|
|
|
* (from the theme side) and sometimes not (from the icon side),
|
2020-01-29 10:08:02 +00:00
|
|
|
|
* but we never take another lock after taking it, so this is safe.
|
|
|
|
|
* Since this is a global (not per icon/theme) lock we should never
|
|
|
|
|
* block while holding it.
|
2020-01-24 15:22:26 +00:00
|
|
|
|
*
|
2020-01-29 10:08:02 +00:00
|
|
|
|
* Sometimes there are "weak" references to the icon theme that can
|
|
|
|
|
* call into the icon theme. For example, from the "theme-changed"
|
2020-01-24 15:22:26 +00:00
|
|
|
|
* signal. Since these don't own the theme they can run in parallel
|
2020-01-29 10:08:02 +00:00
|
|
|
|
* with some other thread which could be finalizing the theme. To
|
|
|
|
|
* avoid this all such references are done via the GtkIconThemeRef
|
|
|
|
|
* object which contains an NULL:able pointer to the theme and the
|
|
|
|
|
* main lock for that theme. Using this we can safely generate a ref
|
|
|
|
|
* for the theme if it still lives (or get NULL if it doesn't).
|
|
|
|
|
*
|
|
|
|
|
* The icon theme needs to call into the icons sometimes, for example
|
|
|
|
|
* when checking if it should be cached (icon_should_cache__unlocked)
|
|
|
|
|
* this takes the icon->texture_lock while the icon theme is locked.
|
|
|
|
|
* In order to avoid ABBA style deadlocks this means the icon code
|
|
|
|
|
* should never try to lock an icon theme.
|
2020-01-24 15:22:26 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2014-07-10 01:12:08 +00:00
|
|
|
|
#define FALLBACK_ICON_THEME "hicolor"
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
|
{
|
2020-01-30 08:12:36 +00:00
|
|
|
|
ICON_THEME_DIR_FIXED,
|
|
|
|
|
ICON_THEME_DIR_SCALABLE,
|
2003-07-02 22:44:09 +00:00
|
|
|
|
ICON_THEME_DIR_THRESHOLD,
|
|
|
|
|
ICON_THEME_DIR_UNTHEMED
|
|
|
|
|
} IconThemeDirType;
|
|
|
|
|
|
2012-11-26 12:49:49 +00:00
|
|
|
|
#if 0
|
|
|
|
|
#define DEBUG_CACHE(args) g_print args
|
|
|
|
|
#else
|
|
|
|
|
#define DEBUG_CACHE(args)
|
|
|
|
|
#endif
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-01 11:25:44 +00:00
|
|
|
|
#define LRU_CACHE_SIZE 100
|
|
|
|
|
#define MAX_LRU_TEXTURE_SIZE 128
|
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
typedef struct _GtkIconPaintableClass GtkIconPaintableClass;
|
|
|
|
|
typedef struct _GtkIconThemeClass GtkIconThemeClass;
|
2019-05-26 19:33:10 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
typedef struct _GtkIconThemeRef GtkIconThemeRef;
|
|
|
|
|
|
2019-05-26 19:33:10 +00:00
|
|
|
|
/**
|
|
|
|
|
* GtkIconTheme:
|
|
|
|
|
*
|
|
|
|
|
* Acts as a database of information about an icon theme.
|
|
|
|
|
* Normally, you retrieve the icon theme for a particular
|
|
|
|
|
* display using gtk_icon_theme_get_for_display() and it
|
|
|
|
|
* will contain information about current icon theme for
|
|
|
|
|
* that display, but you can also create a new #GtkIconTheme
|
|
|
|
|
* object and set the icon theme name explicitly using
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* gtk_icon_theme_set_theme_name().
|
2019-05-26 19:33:10 +00:00
|
|
|
|
*/
|
|
|
|
|
struct _GtkIconTheme
|
|
|
|
|
{
|
|
|
|
|
GObject parent_instance;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
GtkIconThemeRef *ref;
|
2019-05-26 19:33:10 +00:00
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GHashTable *icon_cache; /* Protected by icon_cache lock */
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *lru_cache[LRU_CACHE_SIZE]; /* Protected by icon_cache lock */
|
|
|
|
|
int lru_cache_current; /* Protected by icon_cache lock */
|
2019-09-01 11:25:44 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
char *current_theme;
|
|
|
|
|
char **search_path;
|
|
|
|
|
char **resource_path;
|
2011-04-12 16:33:04 +00:00
|
|
|
|
|
2017-10-31 01:59:06 +00:00
|
|
|
|
guint custom_theme : 1;
|
|
|
|
|
guint is_display_singleton : 1;
|
|
|
|
|
guint pixbuf_supports_svg : 1;
|
|
|
|
|
guint themes_valid : 1;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
/* A list of all the themes needed to look up icons.
|
|
|
|
|
* In search order, without duplicates
|
|
|
|
|
*/
|
|
|
|
|
GList *themes;
|
|
|
|
|
GHashTable *unthemed_icons;
|
2011-04-12 16:33:04 +00:00
|
|
|
|
|
2017-10-31 01:59:06 +00:00
|
|
|
|
/* GdkDisplay for the icon theme (may be NULL) */
|
|
|
|
|
GdkDisplay *display;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
GtkSettings *display_settings;
|
2011-04-12 16:33:04 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
/* time when we last stat:ed for theme changes */
|
2020-07-31 15:22:16 +00:00
|
|
|
|
gint64 last_stat_time;
|
2020-04-25 18:18:29 +00:00
|
|
|
|
GArray *dir_mtimes;
|
2005-08-12 18:39:17 +00:00
|
|
|
|
|
2013-06-19 09:06:20 +00:00
|
|
|
|
gulong theme_changed_idle;
|
2020-04-22 17:47:17 +00:00
|
|
|
|
|
|
|
|
|
int serial;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
};
|
|
|
|
|
|
2019-05-26 19:33:10 +00:00
|
|
|
|
struct _GtkIconThemeClass
|
|
|
|
|
{
|
|
|
|
|
GObjectClass parent_class;
|
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
void (* changed) (GtkIconTheme *self);
|
2019-05-26 19:33:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
2012-11-26 12:49:49 +00:00
|
|
|
|
typedef struct {
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char **icon_names;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size;
|
|
|
|
|
int scale;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
GtkIconLookupFlags flags;
|
2020-01-30 09:52:09 +00:00
|
|
|
|
} IconKey;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
struct _GtkIconPaintableClass
|
2013-02-13 14:05:02 +00:00
|
|
|
|
{
|
|
|
|
|
GObjectClass parent_class;
|
|
|
|
|
};
|
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
/* This lock protects both IconTheme.icon_cache and the dependent Icon.in_cache.
|
2020-01-24 15:22:26 +00:00
|
|
|
|
* Its a global lock, so hold it only for short times. */
|
2020-01-28 14:43:51 +00:00
|
|
|
|
G_LOCK_DEFINE_STATIC(icon_cache);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
2019-05-26 19:33:10 +00:00
|
|
|
|
/**
|
2020-02-04 16:19:22 +00:00
|
|
|
|
* GtkIconPaintable:
|
2019-05-26 19:33:10 +00:00
|
|
|
|
*
|
|
|
|
|
* Contains information found when looking up an icon in
|
2020-01-30 09:44:12 +00:00
|
|
|
|
* an icon theme and supports painting it as a #GdkPaintable.
|
2019-05-26 19:33:10 +00:00
|
|
|
|
*/
|
2020-02-04 16:19:22 +00:00
|
|
|
|
struct _GtkIconPaintable
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2013-02-13 14:05:02 +00:00
|
|
|
|
GObject parent_instance;
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
/* Information about the source
|
|
|
|
|
*/
|
2020-01-30 09:52:09 +00:00
|
|
|
|
IconKey key;
|
2020-01-28 14:43:51 +00:00
|
|
|
|
GtkIconTheme *in_cache; /* Protected by icon_cache lock */
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *icon_name;
|
|
|
|
|
char *filename;
|
2008-05-29 14:33:49 +00:00
|
|
|
|
GLoadableIcon *loadable;
|
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
/* win32 icon (if there is any) */
|
|
|
|
|
GdkPixbuf *win32_icon;
|
|
|
|
|
#endif
|
Update spec.
2005-03-15 Anders Carlsson <andersca@imendio.com>
* docs/iconcache.txt:
Update spec.
* gtk/gtkiconcache.c: (find_image_offset),
(_gtk_icon_cache_get_icon_flags), (_gtk_icon_cache_add_icons),
(_gtk_icon_cache_get_icon), (_gtk_icon_cache_get_icon_data):
* gtk/gtkiconcache.h:
Update to be able to fetch pixbuf data and icon metadata.
* gtk/gtkicontheme.c: (theme_lookup_icon), (gtk_icon_info_free),
(icon_info_ensure_scale_and_pixbuf):
Use new cache functions.
* gtk/updateiconcache.c: (foreach_remove_func), (load_icon_data),
(maybe_cache_image_data), (scan_directory), (write_pixdata),
(get_image_meta_data_size), (get_image_pixel_data_size),
(get_image_data_size), (get_single_node_size), (get_bucket_size),
(write_bucket), (main):
Update to write pixbuf data as well as information from .icon
files.
2005-03-15 13:18:25 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
/* Parameters influencing the scaled icon
|
|
|
|
|
*/
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int desired_size;
|
|
|
|
|
int desired_scale;
|
2014-06-14 22:54:24 +00:00
|
|
|
|
guint is_svg : 1;
|
2014-06-20 04:35:57 +00:00
|
|
|
|
guint is_resource : 1;
|
2020-02-05 16:08:29 +00:00
|
|
|
|
guint is_symbolic : 1;
|
2011-04-12 16:33:04 +00:00
|
|
|
|
|
2020-01-24 16:46:57 +00:00
|
|
|
|
/* Cached information if we go ahead and try to load the icon.
|
|
|
|
|
*
|
2020-01-29 10:08:02 +00:00
|
|
|
|
* All access to these are protected by the texture_lock. Everything
|
2020-01-24 16:46:57 +00:00
|
|
|
|
* above is immutable after construction and can be used without
|
|
|
|
|
* locks.
|
2003-07-02 22:44:09 +00:00
|
|
|
|
*/
|
2020-01-29 10:08:02 +00:00
|
|
|
|
GMutex texture_lock;
|
2020-01-24 16:46:57 +00:00
|
|
|
|
|
2017-11-02 20:39:00 +00:00
|
|
|
|
GdkTexture *texture;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *name;
|
|
|
|
|
char *display_name;
|
|
|
|
|
char *comment;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
GArray *dir_sizes; /* IconThemeDirSize */
|
|
|
|
|
GArray *dirs; /* IconThemeDir */
|
2020-02-07 10:54:00 +00:00
|
|
|
|
GtkStringSet icons;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
} IconTheme;
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
guint16 dir_index; /* index in dirs */
|
|
|
|
|
guint8 best_suffix;
|
|
|
|
|
guint8 best_suffix_no_svg;
|
|
|
|
|
} IconThemeFile;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
IconThemeDirType type;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size;
|
|
|
|
|
int min_size;
|
|
|
|
|
int max_size;
|
|
|
|
|
int threshold;
|
|
|
|
|
int scale;
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
GArray *icon_files;
|
2020-02-07 10:54:00 +00:00
|
|
|
|
GHashTable *icon_hash; /* name (interned) -> file index */
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
} IconThemeDirSize;
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
gboolean is_resource;
|
|
|
|
|
char *path; /* e.g. "/usr/share/icons/hicolor/32x32/apps" */
|
2003-07-02 22:44:09 +00:00
|
|
|
|
} IconThemeDir;
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *svg_filename;
|
|
|
|
|
char *no_svg_filename;
|
2014-06-30 21:02:41 +00:00
|
|
|
|
gboolean is_resource;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
} UnthemedIcon;
|
|
|
|
|
|
2020-01-30 08:12:36 +00:00
|
|
|
|
typedef struct
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *dir;
|
2015-02-23 20:49:08 +00:00
|
|
|
|
time_t mtime;
|
2005-04-06 03:34:38 +00:00
|
|
|
|
GtkIconCache *cache;
|
2015-02-23 20:49:08 +00:00
|
|
|
|
gboolean exists;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
} IconThemeDirMtime;
|
|
|
|
|
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
static void gtk_icon_theme_finalize (GObject *object);
|
|
|
|
|
static void gtk_icon_theme_dispose (GObject *object);
|
|
|
|
|
static IconTheme * theme_new (const char *theme_name,
|
|
|
|
|
GKeyFile *theme_file);
|
|
|
|
|
static void theme_dir_size_destroy (IconThemeDirSize *dir_size);
|
|
|
|
|
static void theme_dir_destroy (IconThemeDir *dir);
|
|
|
|
|
static void theme_destroy (IconTheme *theme);
|
|
|
|
|
static GtkIconPaintable *theme_lookup_icon (IconTheme *theme,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *icon_name,
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size,
|
|
|
|
|
int scale,
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
gboolean allow_svg);
|
|
|
|
|
static gboolean theme_has_icon (IconTheme *theme,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *icon_name);
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
static void theme_subdir_load (GtkIconTheme *self,
|
|
|
|
|
IconTheme *theme,
|
|
|
|
|
GKeyFile *theme_file,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *subdir);
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
static void do_theme_change (GtkIconTheme *self);
|
|
|
|
|
static void blow_themes (GtkIconTheme *self);
|
|
|
|
|
static gboolean rescan_themes (GtkIconTheme *self);
|
2020-02-10 10:40:00 +00:00
|
|
|
|
static GtkIconPaintable *icon_paintable_new (const char *icon_name,
|
|
|
|
|
int desired_size,
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
int desired_scale);
|
2020-07-24 18:40:36 +00:00
|
|
|
|
static IconCacheFlag suffix_from_name (const char *name);
|
2020-02-05 16:08:29 +00:00
|
|
|
|
static void icon_ensure_texture__locked (GtkIconPaintable *icon,
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
gboolean in_thread);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
static void gtk_icon_theme_unset_display (GtkIconTheme *self);
|
|
|
|
|
static void gtk_icon_theme_set_display (GtkIconTheme *self,
|
|
|
|
|
GdkDisplay *display);
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
static void update_current_theme__mainthread (GtkIconTheme *self);
|
|
|
|
|
static gboolean ensure_valid_themes (GtkIconTheme *self,
|
|
|
|
|
gboolean non_blocking);
|
|
|
|
|
|
2020-02-04 08:35:20 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
static guint signal_changed = 0;
|
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
/* This is like a weak ref with a lock, anyone doing
|
|
|
|
|
* operations on the theme must take the lock in this,
|
|
|
|
|
* but you can also take the lock even if the theme
|
|
|
|
|
* has been finalized (but theme will then be NULL).
|
|
|
|
|
*
|
|
|
|
|
* This is used to avoid race conditions where signals
|
|
|
|
|
* like theme-changed happen on the main thread while
|
|
|
|
|
* the last active owning ref of the icon theme is
|
|
|
|
|
* on some thread.
|
|
|
|
|
*/
|
|
|
|
|
struct _GtkIconThemeRef
|
|
|
|
|
{
|
|
|
|
|
gatomicrefcount count;
|
|
|
|
|
GMutex lock;
|
|
|
|
|
GtkIconTheme *theme;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static GtkIconThemeRef *
|
|
|
|
|
gtk_icon_theme_ref_new (GtkIconTheme *theme)
|
|
|
|
|
{
|
|
|
|
|
GtkIconThemeRef *ref = g_new0 (GtkIconThemeRef, 1);
|
|
|
|
|
|
|
|
|
|
g_atomic_ref_count_init (&ref->count);
|
|
|
|
|
g_mutex_init (&ref->lock);
|
|
|
|
|
ref->theme = theme;
|
|
|
|
|
|
|
|
|
|
return ref;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GtkIconThemeRef *
|
|
|
|
|
gtk_icon_theme_ref_ref (GtkIconThemeRef *ref)
|
|
|
|
|
{
|
|
|
|
|
g_atomic_ref_count_inc (&ref->count);
|
|
|
|
|
return ref;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_ref_unref (GtkIconThemeRef *ref)
|
|
|
|
|
{
|
|
|
|
|
if (g_atomic_ref_count_dec (&ref->count))
|
|
|
|
|
{
|
|
|
|
|
g_assert (ref->theme == NULL);
|
|
|
|
|
g_mutex_clear (&ref->lock);
|
|
|
|
|
g_free (ref);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Take the lock and if available ensure the theme lives until (at
|
|
|
|
|
* least) ref_release is called. */
|
|
|
|
|
static GtkIconTheme *
|
|
|
|
|
gtk_icon_theme_ref_aquire (GtkIconThemeRef *ref)
|
|
|
|
|
{
|
|
|
|
|
g_mutex_lock (&ref->lock);
|
|
|
|
|
if (ref->theme)
|
|
|
|
|
g_object_ref (ref->theme);
|
|
|
|
|
return ref->theme;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_ref_release (GtkIconThemeRef *ref)
|
|
|
|
|
{
|
2020-04-22 12:20:33 +00:00
|
|
|
|
GtkIconTheme *theme;
|
|
|
|
|
|
2020-05-28 08:00:03 +00:00
|
|
|
|
/* Get a pointer to the theme, because when we unlock it could become NULLed by dispose, this pointer still owns a ref */
|
2020-04-22 12:20:33 +00:00
|
|
|
|
theme = ref->theme;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
g_mutex_unlock (&ref->lock);
|
2020-04-22 12:20:33 +00:00
|
|
|
|
|
2020-05-28 08:00:03 +00:00
|
|
|
|
/* Then unref outside the lock, because otherwise if this is the last ref the dispose handler would deadlock trying to NULL ref->theme */
|
2020-04-22 12:20:33 +00:00
|
|
|
|
if (theme)
|
|
|
|
|
g_object_unref (theme);
|
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_ref_dispose (GtkIconThemeRef *ref)
|
|
|
|
|
{
|
|
|
|
|
gtk_icon_theme_ref_aquire (ref);
|
|
|
|
|
ref->theme = NULL;
|
|
|
|
|
gtk_icon_theme_ref_release (ref);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_lock (GtkIconTheme *self)
|
|
|
|
|
{
|
|
|
|
|
g_mutex_lock (&self->ref->lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_unlock (GtkIconTheme *self)
|
|
|
|
|
{
|
|
|
|
|
g_mutex_unlock (&self->ref->lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-11-26 12:49:49 +00:00
|
|
|
|
static guint
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon_key_hash (gconstpointer _key)
|
2012-11-26 12:49:49 +00:00
|
|
|
|
{
|
2020-01-30 09:52:09 +00:00
|
|
|
|
const IconKey *key = _key;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
guint h = 0;
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; key->icon_names[i] != NULL; i++)
|
|
|
|
|
h ^= g_str_hash (key->icon_names[i]);
|
|
|
|
|
|
|
|
|
|
h ^= key->size * 0x10001;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
h ^= key->scale * 0x1000010;
|
|
|
|
|
h ^= key->flags * 0x100000100;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon_key_equal (gconstpointer _a,
|
|
|
|
|
gconstpointer _b)
|
2012-11-26 12:49:49 +00:00
|
|
|
|
{
|
2020-01-30 09:52:09 +00:00
|
|
|
|
const IconKey *a = _a;
|
|
|
|
|
const IconKey *b = _b;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (a->size != b->size)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2013-05-10 16:06:00 +00:00
|
|
|
|
if (a->scale != b->scale)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2012-11-26 12:49:49 +00:00
|
|
|
|
if (a->flags != b->flags)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
for (i = 0;
|
|
|
|
|
a->icon_names[i] != NULL &&
|
|
|
|
|
b->icon_names[i] != NULL; i++)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (a->icon_names[i], b->icon_names[i]) != 0)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
return FALSE;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return a->icon_names[i] == NULL && b->icon_names[i] == NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
/****************** Icon cache ***********************
|
|
|
|
|
*
|
|
|
|
|
* The icon cache, this spans both GtkIconTheme and GtkIcon, so the locking is
|
|
|
|
|
* a bit tricky. Never do block with the lock held, and never do any
|
|
|
|
|
* callouts to other code. In particular, don't call theme or finalizers
|
|
|
|
|
* because that will take the lock when removing from the icon cache.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* This is called with icon_cache lock held so must not take any locks */
|
2020-01-24 16:46:57 +00:00
|
|
|
|
static gboolean
|
2020-02-04 16:19:22 +00:00
|
|
|
|
_icon_cache_should_lru_cache (GtkIconPaintable *icon)
|
2020-01-24 16:46:57 +00:00
|
|
|
|
{
|
2020-01-30 09:52:09 +00:00
|
|
|
|
return icon->desired_size <= MAX_LRU_TEXTURE_SIZE;
|
2020-01-24 16:46:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
/* This returns the old lru element because we can't unref it with
|
|
|
|
|
* the lock held */
|
2020-02-04 16:19:22 +00:00
|
|
|
|
static GtkIconPaintable *
|
|
|
|
|
_icon_cache_add_to_lru_cache (GtkIconTheme *theme,
|
|
|
|
|
GtkIconPaintable *icon)
|
2020-01-24 16:46:57 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *old_icon = NULL;
|
2020-01-24 16:46:57 +00:00
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
/* Avoid storing the same info multiple times in a row */
|
|
|
|
|
if (theme->lru_cache[theme->lru_cache_current] != icon)
|
|
|
|
|
{
|
|
|
|
|
theme->lru_cache_current = (theme->lru_cache_current + 1) % LRU_CACHE_SIZE;
|
|
|
|
|
old_icon = theme->lru_cache[theme->lru_cache_current];
|
|
|
|
|
theme->lru_cache[theme->lru_cache_current] = g_object_ref (icon);
|
|
|
|
|
}
|
2020-01-24 16:46:57 +00:00
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
return old_icon;
|
2020-01-24 16:46:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
static GtkIconPaintable *
|
2020-01-30 11:27:15 +00:00
|
|
|
|
icon_cache_lookup (GtkIconTheme *theme,
|
|
|
|
|
IconKey *key)
|
2019-09-01 11:25:44 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *old_icon = NULL;
|
|
|
|
|
GtkIconPaintable *icon;
|
2020-01-29 10:08:02 +00:00
|
|
|
|
|
|
|
|
|
G_LOCK (icon_cache);
|
|
|
|
|
|
|
|
|
|
icon = g_hash_table_lookup (theme->icon_cache, key);
|
|
|
|
|
if (icon != NULL)
|
2019-09-01 11:25:44 +00:00
|
|
|
|
{
|
2020-01-29 10:08:02 +00:00
|
|
|
|
DEBUG_CACHE (("cache hit %p (%s %d 0x%x) (cache size %d)\n",
|
|
|
|
|
icon,
|
|
|
|
|
g_strjoinv (",", icon->key.icon_names),
|
|
|
|
|
icon->key.size, icon->key.flags,
|
|
|
|
|
g_hash_table_size (theme->icon_cache)));
|
|
|
|
|
|
|
|
|
|
icon = g_object_ref (icon);
|
|
|
|
|
|
|
|
|
|
/* Move item to front in LRU cache */
|
|
|
|
|
if (_icon_cache_should_lru_cache (icon))
|
|
|
|
|
old_icon = _icon_cache_add_to_lru_cache (theme, icon);
|
2019-09-01 11:25:44 +00:00
|
|
|
|
}
|
2020-01-29 10:08:02 +00:00
|
|
|
|
|
|
|
|
|
G_UNLOCK (icon_cache);
|
|
|
|
|
|
|
|
|
|
/* Call potential finalizer outside the lock */
|
|
|
|
|
if (old_icon)
|
|
|
|
|
g_object_unref (old_icon);
|
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-30 09:52:09 +00:00
|
|
|
|
/* The icon was removed from the icon_hash hash table.
|
2020-01-29 10:08:02 +00:00
|
|
|
|
* This is a callback from the icon_cache hashtable, so the icon_cache lock is already held.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
2020-02-04 16:19:22 +00:00
|
|
|
|
icon_uncached_cb (GtkIconPaintable *icon)
|
2020-01-29 10:08:02 +00:00
|
|
|
|
{
|
|
|
|
|
DEBUG_CACHE (("removing %p (%s %d 0x%x) from cache (icon_them: %p) (cache size %d)\n",
|
|
|
|
|
icon,
|
|
|
|
|
g_strjoinv (",", icon->key.icon_names),
|
|
|
|
|
icon->key.size, icon->key.flags,
|
|
|
|
|
self,
|
|
|
|
|
icon_theme != NULL ? g_hash_table_size (self->icon_cache) : 0));
|
|
|
|
|
g_assert (icon->in_cache != NULL);
|
|
|
|
|
icon->in_cache = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-04 16:19:22 +00:00
|
|
|
|
icon_cache_mark_used_if_cached (GtkIconPaintable *icon)
|
2020-01-29 10:08:02 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *old_icon = NULL;
|
2020-01-29 10:08:02 +00:00
|
|
|
|
|
|
|
|
|
if (!_icon_cache_should_lru_cache (icon))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
G_LOCK (icon_cache);
|
|
|
|
|
if (icon->in_cache)
|
|
|
|
|
old_icon = _icon_cache_add_to_lru_cache (icon->in_cache, icon);
|
|
|
|
|
G_UNLOCK (icon_cache);
|
|
|
|
|
|
|
|
|
|
/* Call potential finalizers outside the lock */
|
|
|
|
|
if (old_icon)
|
|
|
|
|
g_object_unref (old_icon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-04 16:19:22 +00:00
|
|
|
|
icon_cache_add (GtkIconTheme *theme,
|
|
|
|
|
GtkIconPaintable *icon)
|
2020-01-29 10:08:02 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *old_icon = NULL;
|
2020-01-29 10:08:02 +00:00
|
|
|
|
|
|
|
|
|
G_LOCK (icon_cache);
|
|
|
|
|
icon->in_cache = theme;
|
|
|
|
|
g_hash_table_insert (theme->icon_cache, &icon->key, icon);
|
|
|
|
|
|
|
|
|
|
if (_icon_cache_should_lru_cache (icon))
|
|
|
|
|
old_icon = _icon_cache_add_to_lru_cache (theme, icon);
|
|
|
|
|
DEBUG_CACHE (("adding %p (%s %d 0x%x) to cache (cache size %d)\n",
|
|
|
|
|
icon,
|
|
|
|
|
g_strjoinv (",", icon->key.icon_names),
|
|
|
|
|
icon->key.size, icon->key.flags,
|
|
|
|
|
g_hash_table_size (theme->icon_cache)));
|
|
|
|
|
G_UNLOCK (icon_cache);
|
|
|
|
|
|
|
|
|
|
/* Call potential finalizer outside the lock */
|
|
|
|
|
if (old_icon)
|
|
|
|
|
g_object_unref (old_icon);
|
2019-09-01 11:25:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-04 16:19:22 +00:00
|
|
|
|
icon_cache_remove (GtkIconPaintable *icon)
|
2020-01-29 10:08:02 +00:00
|
|
|
|
{
|
|
|
|
|
G_LOCK (icon_cache);
|
|
|
|
|
if (icon->in_cache)
|
|
|
|
|
g_hash_table_remove (icon->in_cache->icon_cache, &icon->key);
|
|
|
|
|
G_UNLOCK (icon_cache);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
icon_cache_clear (GtkIconTheme *theme)
|
2019-09-01 11:25:44 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *old_icons[LRU_CACHE_SIZE];
|
2019-09-01 11:25:44 +00:00
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
G_LOCK (icon_cache);
|
|
|
|
|
g_hash_table_remove_all (theme->icon_cache);
|
2019-09-01 11:25:44 +00:00
|
|
|
|
for (i = 0; i < LRU_CACHE_SIZE; i ++)
|
2020-01-29 10:08:02 +00:00
|
|
|
|
{
|
|
|
|
|
old_icons[i] = theme->lru_cache[i];
|
|
|
|
|
theme->lru_cache[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
G_UNLOCK (icon_cache);
|
|
|
|
|
|
|
|
|
|
/* Call potential finalizers outside the lock */
|
|
|
|
|
for (i = 0; i < LRU_CACHE_SIZE; i ++)
|
|
|
|
|
{
|
|
|
|
|
if (old_icons[i] != NULL)
|
|
|
|
|
g_object_unref (old_icons[i]);
|
|
|
|
|
}
|
2019-09-01 11:25:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
/****************** End of icon cache ***********************/
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (GtkIconTheme, gtk_icon_theme, G_TYPE_OBJECT)
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_theme_new:
|
2020-01-30 08:12:36 +00:00
|
|
|
|
*
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* Creates a new icon theme object. Icon theme objects are used
|
|
|
|
|
* to lookup up an icon by name in a particular icon theme.
|
2020-02-01 22:38:49 +00:00
|
|
|
|
* Usually, you’ll want to use gtk_icon_theme_get_for_display()
|
|
|
|
|
* rather than creating a new icon theme object for scratch.
|
2020-01-30 08:12:36 +00:00
|
|
|
|
*
|
2014-02-19 23:49:43 +00:00
|
|
|
|
* Returns: the newly created #GtkIconTheme object.
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*/
|
2003-07-02 22:44:09 +00:00
|
|
|
|
GtkIconTheme *
|
|
|
|
|
gtk_icon_theme_new (void)
|
|
|
|
|
{
|
|
|
|
|
return g_object_new (GTK_TYPE_ICON_THEME, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-29 10:38:05 +00:00
|
|
|
|
static void
|
|
|
|
|
load_theme_thread (GTask *task,
|
|
|
|
|
gpointer source_object,
|
|
|
|
|
gpointer task_data,
|
|
|
|
|
GCancellable *cancellable)
|
|
|
|
|
{
|
|
|
|
|
GtkIconTheme *self = GTK_ICON_THEME (source_object);
|
|
|
|
|
|
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
ensure_valid_themes (self, FALSE);
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
|
|
|
|
g_task_return_pointer (task, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_load_in_thread (GtkIconTheme *self)
|
|
|
|
|
{
|
|
|
|
|
GTask *task;
|
|
|
|
|
|
|
|
|
|
task = g_task_new (self, NULL, NULL, NULL);
|
|
|
|
|
g_task_set_task_data (task, g_object_ref (self), g_object_unref);
|
|
|
|
|
g_task_run_in_thread (task, load_theme_thread);
|
2020-02-04 23:25:15 +00:00
|
|
|
|
g_object_unref (task);
|
2020-01-29 10:38:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
/**
|
2017-10-31 01:59:06 +00:00
|
|
|
|
* gtk_icon_theme_get_for_display:
|
|
|
|
|
* @display: a #GdkDisplay
|
2020-01-30 08:12:36 +00:00
|
|
|
|
*
|
2017-10-31 01:59:06 +00:00
|
|
|
|
* Gets the icon theme object associated with @display; if this
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* function has not previously been called for the given
|
2017-10-31 01:59:06 +00:00
|
|
|
|
* display, a new icon theme object will be created and
|
|
|
|
|
* associated with the display. Icon theme objects are
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* fairly expensive to create, so using this function
|
|
|
|
|
* is usually a better choice than calling than gtk_icon_theme_new()
|
2017-10-31 01:59:06 +00:00
|
|
|
|
* and setting the display yourself; by using this function
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* a single icon theme object will be shared between users.
|
2009-12-10 10:23:40 +00:00
|
|
|
|
*
|
2014-02-19 23:49:43 +00:00
|
|
|
|
* Returns: (transfer none): A unique #GtkIconTheme associated with
|
2017-10-31 01:59:06 +00:00
|
|
|
|
* the given display. This icon theme is associated with
|
|
|
|
|
* the display and can be used as long as the display
|
2005-07-13 04:53:49 +00:00
|
|
|
|
* is open. Do not ref or unref it.
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*/
|
2003-07-02 22:44:09 +00:00
|
|
|
|
GtkIconTheme *
|
2017-10-31 01:59:06 +00:00
|
|
|
|
gtk_icon_theme_get_for_display (GdkDisplay *display)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
GtkIconTheme *self;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2017-10-31 01:59:06 +00:00
|
|
|
|
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self = g_object_get_data (G_OBJECT (display), "gtk-icon-theme");
|
|
|
|
|
if (!self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self = gtk_icon_theme_new ();
|
|
|
|
|
self->is_display_singleton = TRUE;
|
|
|
|
|
g_object_set_data (G_OBJECT (display), I_("gtk-icon-theme"), self);
|
2020-01-29 10:38:05 +00:00
|
|
|
|
|
2020-01-30 17:19:56 +00:00
|
|
|
|
/* Call this after setting the user-data, because it recurses into gtk_icon_theme_get_for_display via the thememing machinery */
|
|
|
|
|
gtk_icon_theme_set_display (self, display);
|
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
/* Queue early read of the default themes, we read the icon theme name in set_display(). */
|
2020-01-29 10:38:05 +00:00
|
|
|
|
gtk_icon_theme_load_in_thread (self);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
return self;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
enum {
|
|
|
|
|
PROP_DISPLAY = 1,
|
|
|
|
|
PROP_ICON_NAMES,
|
|
|
|
|
PROP_SEARCH_PATH,
|
|
|
|
|
PROP_RESOURCE_PATH,
|
|
|
|
|
PROP_THEME_NAME,
|
|
|
|
|
LAST_PROP
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static GParamSpec *props[LAST_PROP];
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_get_property (GObject *object,
|
|
|
|
|
guint prop_id,
|
|
|
|
|
GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
GtkIconTheme *self = GTK_ICON_THEME (object);
|
|
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
|
{
|
|
|
|
|
case PROP_DISPLAY:
|
|
|
|
|
g_value_set_object (value, self->display);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_ICON_NAMES:
|
|
|
|
|
g_value_take_boxed (value, gtk_icon_theme_get_icon_names (self));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_SEARCH_PATH:
|
|
|
|
|
g_value_set_boxed (value, self->search_path);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_RESOURCE_PATH:
|
|
|
|
|
g_value_set_boxed (value, self->resource_path);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_THEME_NAME:
|
|
|
|
|
g_value_take_string (value, gtk_icon_theme_get_theme_name (self));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_set_property (GObject *object,
|
|
|
|
|
guint prop_id,
|
|
|
|
|
const GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
GtkIconTheme *self = GTK_ICON_THEME (object);
|
|
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
|
{
|
|
|
|
|
case PROP_DISPLAY:
|
|
|
|
|
gtk_icon_theme_set_display (self, g_value_get_object (value));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_SEARCH_PATH:
|
|
|
|
|
gtk_icon_theme_set_search_path (self, g_value_get_boxed (value));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_RESOURCE_PATH:
|
|
|
|
|
gtk_icon_theme_set_resource_path (self, g_value_get_boxed (value));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_THEME_NAME:
|
|
|
|
|
gtk_icon_theme_set_theme_name (self, g_value_get_string (value));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_class_init (GtkIconThemeClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
|
|
gobject_class->finalize = gtk_icon_theme_finalize;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gobject_class->dispose = gtk_icon_theme_dispose;
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gobject_class->get_property = gtk_icon_theme_get_property;
|
|
|
|
|
gobject_class->set_property = gtk_icon_theme_set_property;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2014-06-19 23:42:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* GtkIconTheme::changed:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: the icon theme
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*
|
2020-09-12 16:01:04 +00:00
|
|
|
|
* Emitted when the current icon theme is switched or GTK detects
|
2014-06-19 23:42:53 +00:00
|
|
|
|
* that a change has occurred in the contents of the current
|
|
|
|
|
* icon theme.
|
|
|
|
|
*/
|
2005-09-01 05:11:46 +00:00
|
|
|
|
signal_changed = g_signal_new (I_("changed"),
|
2014-06-19 23:42:53 +00:00
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
G_STRUCT_OFFSET (GtkIconThemeClass, changed),
|
|
|
|
|
NULL, NULL,
|
2019-05-29 20:05:19 +00:00
|
|
|
|
NULL,
|
2014-06-19 23:42:53 +00:00
|
|
|
|
G_TYPE_NONE, 0);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GtkIconTheme:display:
|
|
|
|
|
*
|
|
|
|
|
* The display that this icon theme object is attached to.
|
|
|
|
|
*/
|
|
|
|
|
props[PROP_DISPLAY] =
|
|
|
|
|
g_param_spec_object ("display",
|
|
|
|
|
P_("Display"),
|
|
|
|
|
P_("Display"),
|
|
|
|
|
GDK_TYPE_DISPLAY,
|
|
|
|
|
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GtkIconTheme:icon-names:
|
|
|
|
|
*
|
|
|
|
|
* The icon names that are supported by the icon theme.
|
|
|
|
|
*/
|
|
|
|
|
props[PROP_ICON_NAMES] =
|
|
|
|
|
g_param_spec_boxed ("icon-names",
|
|
|
|
|
P_("Supported icon names"),
|
|
|
|
|
P_("Supported icon names"),
|
|
|
|
|
G_TYPE_STRV,
|
|
|
|
|
GTK_PARAM_READABLE);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GtkIconTheme:search-path:
|
|
|
|
|
*
|
|
|
|
|
* The search path for this icon theme.
|
|
|
|
|
*
|
|
|
|
|
* When looking for icons, GTK will search for a subdirectory of
|
|
|
|
|
* one or more of the directories in the search path with the same
|
|
|
|
|
* name as the icon theme containing an index.theme file. (Themes
|
|
|
|
|
* from multiple of the path elements are combined to allow themes
|
|
|
|
|
* to be extended by adding icons in the user’s home directory.)
|
|
|
|
|
*/
|
|
|
|
|
props[PROP_SEARCH_PATH] =
|
|
|
|
|
g_param_spec_boxed ("search-path",
|
|
|
|
|
P_("Search path"),
|
|
|
|
|
P_("Search path"),
|
|
|
|
|
G_TYPE_STRV,
|
|
|
|
|
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GtkIconTheme:resource-path:
|
|
|
|
|
*
|
|
|
|
|
* Resource paths that will be looked at when looking for icons,
|
|
|
|
|
* similar to search paths.
|
|
|
|
|
*
|
|
|
|
|
* The resources are considered as part of the hicolor icon theme
|
|
|
|
|
* and must be located in subdirectories that are defined in the
|
|
|
|
|
* hicolor icon theme, such as `@path/16x16/actions/run.png`.
|
|
|
|
|
* Icons that are directly placed in the resource path instead
|
|
|
|
|
* of a subdirectory are also considered as ultimate fallback.
|
|
|
|
|
*/
|
|
|
|
|
props[PROP_RESOURCE_PATH] =
|
|
|
|
|
g_param_spec_boxed ("resource-path",
|
|
|
|
|
P_("Resource path"),
|
|
|
|
|
P_("Resource path"),
|
|
|
|
|
G_TYPE_STRV,
|
|
|
|
|
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GtkIconTheme:theme-name:
|
|
|
|
|
*
|
|
|
|
|
* The name of the icon theme that is being used.
|
|
|
|
|
*
|
|
|
|
|
* Unless set to a different value, this will be the value of
|
|
|
|
|
* the #GtkSettings:gtk-icon-theme-name property of the #GtkSettings
|
|
|
|
|
* object associated to the display of the icontheme object.
|
|
|
|
|
*/
|
|
|
|
|
props[PROP_THEME_NAME] =
|
|
|
|
|
g_param_spec_string ("theme-name",
|
|
|
|
|
P_("Theme name"),
|
|
|
|
|
P_("Theme name"),
|
|
|
|
|
NULL,
|
|
|
|
|
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
|
|
|
|
|
|
g_object_class_install_properties (gobject_class, LAST_PROP, props);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-06-19 23:42:53 +00:00
|
|
|
|
/* Callback when the display that the icon theme is attached
|
2017-10-31 01:59:06 +00:00
|
|
|
|
* to is closed; unset the display, and if it’s the unique theme
|
|
|
|
|
* for the display, drop the reference
|
2003-07-02 22:44:09 +00:00
|
|
|
|
*/
|
|
|
|
|
static void
|
2020-01-24 15:22:26 +00:00
|
|
|
|
display_closed__mainthread_unlocked (GdkDisplay *display,
|
|
|
|
|
gboolean is_error,
|
|
|
|
|
GtkIconThemeRef *ref)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-01-24 15:22:26 +00:00
|
|
|
|
GtkIconTheme *self = gtk_icon_theme_ref_aquire (ref);
|
|
|
|
|
gboolean was_display_singleton;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
if (self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-01-24 15:22:26 +00:00
|
|
|
|
/* This is only set at construction and accessed here in the main thread, so no locking necessary */
|
|
|
|
|
was_display_singleton = self->is_display_singleton;
|
|
|
|
|
if (was_display_singleton)
|
|
|
|
|
{
|
|
|
|
|
g_object_set_data (G_OBJECT (display), I_("gtk-icon-theme"), NULL);
|
|
|
|
|
self->is_display_singleton = FALSE;
|
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gtk_icon_theme_unset_display (self);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
update_current_theme__mainthread (self);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
if (was_display_singleton)
|
|
|
|
|
g_object_unref (self);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_ref_release (ref);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-01-24 15:22:26 +00:00
|
|
|
|
update_current_theme__mainthread (GtkIconTheme *self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2007-03-06 18:26:41 +00:00
|
|
|
|
#define theme_changed(_old, _new) \
|
|
|
|
|
((_old && !_new) || (!_old && _new) || \
|
|
|
|
|
(_old && _new && strcmp (_old, _new) != 0))
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (!self->custom_theme)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *theme = NULL;
|
2006-01-11 06:20:17 +00:00
|
|
|
|
gboolean changed = FALSE;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (self->display)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
GtkSettings *settings = gtk_settings_get_for_display (self->display);
|
2014-06-19 23:42:53 +00:00
|
|
|
|
g_object_get (settings, "gtk-icon-theme-name", &theme, NULL);
|
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (theme_changed (self->current_theme, theme))
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_free (self->current_theme);
|
|
|
|
|
self->current_theme = theme;
|
2014-06-19 23:42:53 +00:00
|
|
|
|
changed = TRUE;
|
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
else
|
2014-06-19 23:42:53 +00:00
|
|
|
|
g_free (theme);
|
2006-01-11 06:20:17 +00:00
|
|
|
|
|
|
|
|
|
if (changed)
|
2019-09-08 12:57:40 +00:00
|
|
|
|
do_theme_change (self);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2007-03-06 18:26:41 +00:00
|
|
|
|
#undef theme_changed
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Callback when the icon theme GtkSetting changes
|
|
|
|
|
*/
|
|
|
|
|
static void
|
2020-01-30 11:27:15 +00:00
|
|
|
|
theme_changed__mainthread_unlocked (GtkSettings *settings,
|
|
|
|
|
GParamSpec *pspec,
|
2020-01-24 15:22:26 +00:00
|
|
|
|
GtkIconThemeRef *ref)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-01-24 15:22:26 +00:00
|
|
|
|
GtkIconTheme *self = gtk_icon_theme_ref_aquire (ref);
|
|
|
|
|
|
|
|
|
|
if (self)
|
2020-01-29 10:38:05 +00:00
|
|
|
|
{
|
|
|
|
|
update_current_theme__mainthread (self);
|
|
|
|
|
|
|
|
|
|
/* Queue early read of the new theme */
|
|
|
|
|
gtk_icon_theme_load_in_thread (self);
|
|
|
|
|
}
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_ref_release (ref);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gtk_icon_theme_unset_display (GtkIconTheme *self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (self->display)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_signal_handlers_disconnect_by_func (self->display,
|
2020-01-24 15:22:26 +00:00
|
|
|
|
(gpointer) display_closed__mainthread_unlocked,
|
|
|
|
|
self->ref);
|
|
|
|
|
g_signal_handlers_disconnect_by_func (self->display_settings,
|
|
|
|
|
(gpointer) theme_changed__mainthread_unlocked,
|
|
|
|
|
self->ref);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->display = NULL;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
self->display_settings = NULL;
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DISPLAY]);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
gtk_icon_theme_set_display (GtkIconTheme *self,
|
2017-10-31 01:59:06 +00:00
|
|
|
|
GdkDisplay *display)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_if_fail (GTK_ICON_THEME (self));
|
2017-10-31 01:59:06 +00:00
|
|
|
|
g_return_if_fail (display == NULL || GDK_IS_DISPLAY (display));
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
g_object_freeze_notify (G_OBJECT (self));
|
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unset_display (self);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
2017-10-31 01:59:06 +00:00
|
|
|
|
if (display)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->display = display;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
self->display_settings = gtk_settings_get_for_display (display);
|
|
|
|
|
|
|
|
|
|
g_signal_connect_data (display, "closed",
|
|
|
|
|
G_CALLBACK (display_closed__mainthread_unlocked),
|
|
|
|
|
gtk_icon_theme_ref_ref (self->ref),
|
|
|
|
|
(GClosureNotify)gtk_icon_theme_ref_unref,
|
|
|
|
|
0);
|
|
|
|
|
g_signal_connect_data (self->display_settings, "notify::gtk-icon-theme-name",
|
|
|
|
|
G_CALLBACK (theme_changed__mainthread_unlocked),
|
|
|
|
|
gtk_icon_theme_ref_ref (self->ref),
|
|
|
|
|
(GClosureNotify)gtk_icon_theme_ref_unref,
|
|
|
|
|
0);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DISPLAY]);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
update_current_theme__mainthread (self);
|
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
g_object_thaw_notify (G_OBJECT (self));
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Checks whether a loader for SVG files has been registered
|
|
|
|
|
* with GdkPixbuf.
|
|
|
|
|
*/
|
|
|
|
|
static gboolean
|
2004-10-28 15:00:05 +00:00
|
|
|
|
pixbuf_supports_svg (void)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2006-10-15 22:58:08 +00:00
|
|
|
|
GSList *formats;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
GSList *tmp_list;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
static int found_svg = -1;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2006-04-04 04:14:17 +00:00
|
|
|
|
if (found_svg != -1)
|
2004-10-19 18:45:41 +00:00
|
|
|
|
return found_svg;
|
2006-10-15 22:58:08 +00:00
|
|
|
|
|
|
|
|
|
formats = gdk_pixbuf_get_formats ();
|
|
|
|
|
|
2020-01-30 08:12:36 +00:00
|
|
|
|
found_svg = FALSE;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
for (tmp_list = formats; tmp_list && !found_svg; tmp_list = tmp_list->next)
|
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char **mime_types = gdk_pixbuf_format_get_mime_types (tmp_list->data);
|
|
|
|
|
char **mime_type;
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
for (mime_type = mime_types; *mime_type && !found_svg; mime_type++)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
|
|
|
|
if (strcmp (*mime_type, "image/svg") == 0)
|
|
|
|
|
found_svg = TRUE;
|
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2003-07-11 20:36:25 +00:00
|
|
|
|
g_strfreev (mime_types);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_slist_free (formats);
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
return found_svg;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 18:18:29 +00:00
|
|
|
|
static void
|
|
|
|
|
free_dir_mtime (IconThemeDirMtime *dir_mtime)
|
|
|
|
|
{
|
|
|
|
|
if (dir_mtime->cache)
|
|
|
|
|
gtk_icon_cache_unref (dir_mtime->cache);
|
|
|
|
|
|
|
|
|
|
g_free (dir_mtime->dir);
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
static void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
gtk_icon_theme_init (GtkIconTheme *self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char * const *xdg_data_dirs;
|
2004-08-17 19:51:11 +00:00
|
|
|
|
int i, j;
|
2020-02-18 05:56:37 +00:00
|
|
|
|
int len;
|
2010-06-22 14:42:00 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
self->ref = gtk_icon_theme_ref_new (self);
|
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
self->icon_cache = g_hash_table_new_full (icon_key_hash, icon_key_equal, NULL,
|
2020-01-29 10:08:02 +00:00
|
|
|
|
(GDestroyNotify)icon_uncached_cb);
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->custom_theme = FALSE;
|
2020-04-25 18:18:29 +00:00
|
|
|
|
self->dir_mtimes = g_array_new (FALSE, TRUE, sizeof (IconThemeDirMtime));
|
|
|
|
|
g_array_set_clear_func (self->dir_mtimes, (GDestroyNotify)free_dir_mtime);
|
2004-08-17 19:51:11 +00:00
|
|
|
|
|
|
|
|
|
xdg_data_dirs = g_get_system_data_dirs ();
|
|
|
|
|
for (i = 0; xdg_data_dirs[i]; i++) ;
|
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
len = 2 * i + 3;
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
self->search_path = g_new (char *, len);
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2004-08-17 19:51:11 +00:00
|
|
|
|
i = 0;
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->search_path[i++] = g_build_filename (g_get_user_data_dir (), "icons", NULL);
|
|
|
|
|
self->search_path[i++] = g_build_filename (g_get_home_dir (), ".icons", NULL);
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
|
|
|
|
for (j = 0; xdg_data_dirs[j]; j++)
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->search_path[i++] = g_build_filename (xdg_data_dirs[j], "icons", NULL);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-30 08:12:36 +00:00
|
|
|
|
for (j = 0; xdg_data_dirs[j]; j++)
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->search_path[i++] = g_build_filename (xdg_data_dirs[j], "pixmaps", NULL);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
self->search_path[i] = NULL;
|
|
|
|
|
|
|
|
|
|
self->resource_path = g_new (char *, 2);
|
|
|
|
|
self->resource_path[0] = g_strdup ("/org/gtk/libgtk/icons/");
|
|
|
|
|
self->resource_path[1] = NULL;
|
2014-06-20 05:04:16 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->themes_valid = FALSE;
|
|
|
|
|
self->themes = NULL;
|
|
|
|
|
self->unthemed_icons = NULL;
|
2019-09-01 09:25:48 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->pixbuf_supports_svg = pixbuf_supports_svg ();
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-08-12 18:39:17 +00:00
|
|
|
|
static gboolean
|
2020-01-24 15:22:26 +00:00
|
|
|
|
theme_changed_idle__mainthread_unlocked (gpointer user_data)
|
2005-08-12 18:39:17 +00:00
|
|
|
|
{
|
2020-01-24 15:22:26 +00:00
|
|
|
|
GtkIconThemeRef *ref = (GtkIconThemeRef *)user_data;
|
2019-09-08 12:57:40 +00:00
|
|
|
|
GtkIconTheme *self;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
GdkDisplay *display = NULL;
|
|
|
|
|
|
|
|
|
|
self = gtk_icon_theme_ref_aquire (ref);
|
|
|
|
|
if (self)
|
|
|
|
|
{
|
|
|
|
|
g_object_ref (self); /* Ensure theme lives during the changed signal emissions */
|
2005-08-12 18:39:17 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
self->theme_changed_idle = 0;
|
2005-08-12 18:39:17 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
if (self->display && self->is_display_singleton)
|
|
|
|
|
display = g_object_ref (self->display);
|
|
|
|
|
}
|
|
|
|
|
gtk_icon_theme_ref_release (ref);
|
2013-06-19 09:06:20 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
if (self)
|
|
|
|
|
{
|
|
|
|
|
/* Emit signals outside locks. */
|
|
|
|
|
g_signal_emit (self, signal_changed, 0);
|
2005-08-12 18:39:17 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
if (display)
|
|
|
|
|
{
|
2020-04-21 14:44:36 +00:00
|
|
|
|
GtkSettings *settings = gtk_settings_get_for_display (self->display);
|
|
|
|
|
gtk_style_provider_changed (GTK_STYLE_PROVIDER (settings));
|
|
|
|
|
gtk_system_setting_changed (display, GTK_SYSTEM_SETTING_ICON_THEME);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
g_object_unref (display);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_object_unref (self);
|
|
|
|
|
}
|
2005-08-12 18:39:17 +00:00
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-19 09:06:20 +00:00
|
|
|
|
static void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
queue_theme_changed (GtkIconTheme *self)
|
2013-06-19 09:06:20 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (!self->theme_changed_idle)
|
2014-03-22 11:44:01 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->theme_changed_idle = g_idle_add_full (GTK_PRIORITY_RESIZE - 2,
|
2020-01-24 15:22:26 +00:00
|
|
|
|
theme_changed_idle__mainthread_unlocked,
|
|
|
|
|
gtk_icon_theme_ref_ref (self->ref),
|
|
|
|
|
(GDestroyNotify)gtk_icon_theme_ref_unref);
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_source_set_name_by_id (self->theme_changed_idle, "[gtk] theme_changed_idle");
|
2014-03-22 11:44:01 +00:00
|
|
|
|
}
|
2013-06-19 09:06:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
static void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
do_theme_change (GtkIconTheme *self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-01-29 10:08:02 +00:00
|
|
|
|
icon_cache_clear (self);
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (!self->themes_valid)
|
2007-03-06 18:26:41 +00:00
|
|
|
|
return;
|
2013-06-19 09:06:20 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
GTK_DISPLAY_NOTE (self->display, ICONTHEME,
|
|
|
|
|
g_message ("change to icon theme \"%s\"", self->current_theme));
|
|
|
|
|
blow_themes (self);
|
2005-08-12 18:39:17 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
queue_theme_changed (self);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
blow_themes (GtkIconTheme *self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (self->themes_valid)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_list_free_full (self->themes, (GDestroyNotify) theme_destroy);
|
2020-04-25 18:18:29 +00:00
|
|
|
|
g_array_set_size (self->dir_mtimes, 0);
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_hash_table_destroy (self->unthemed_icons);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->themes = NULL;
|
|
|
|
|
self->unthemed_icons = NULL;
|
|
|
|
|
self->themes_valid = FALSE;
|
2020-04-22 17:47:17 +00:00
|
|
|
|
self->serial++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
gtk_icon_theme_get_serial (GtkIconTheme *self)
|
|
|
|
|
{
|
|
|
|
|
return self->serial;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_dispose (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
GtkIconTheme *self = GTK_ICON_THEME (object);
|
|
|
|
|
|
|
|
|
|
/* We make sure all outstanding GtkIconThemeRefs to us are NULLed
|
|
|
|
|
* out so that no other threads than the one running finalize will
|
|
|
|
|
* refer to the icon theme after this. This could happen if
|
|
|
|
|
* we finalize on a thread and on the main thread some display or
|
|
|
|
|
* setting signal is emitted.
|
|
|
|
|
*
|
2020-08-21 12:41:13 +00:00
|
|
|
|
* It is possible that before we acquire the lock this happens
|
2020-01-24 15:22:26 +00:00
|
|
|
|
* and the other thread refs the icon theme for some reason, but
|
|
|
|
|
* this is ok as it is allowed to resurrect objects in dispose
|
|
|
|
|
* (but not in finalize).
|
|
|
|
|
*/
|
|
|
|
|
gtk_icon_theme_ref_dispose (self->ref);
|
|
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (gtk_icon_theme_parent_class)->dispose (object);
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
static void
|
|
|
|
|
gtk_icon_theme_finalize (GObject *object)
|
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
GtkIconTheme *self = GTK_ICON_THEME (object);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
/* We don't actually need to take the lock here, because by now
|
|
|
|
|
there can be no other threads that own a ref to this object, but
|
|
|
|
|
technically this is considered "locked" */
|
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
icon_cache_clear (self);
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (self->theme_changed_idle)
|
|
|
|
|
g_source_remove (self->theme_changed_idle);
|
2005-08-12 18:39:17 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gtk_icon_theme_unset_display (self);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_free (self->current_theme);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
g_strfreev (self->search_path);
|
|
|
|
|
g_strfreev (self->resource_path);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
blow_themes (self);
|
2020-04-25 18:18:29 +00:00
|
|
|
|
g_array_free (self->dir_mtimes, TRUE);
|
2004-02-22 02:06:49 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gtk_icon_theme_ref_unref (self->ref);
|
|
|
|
|
|
2019-09-01 11:25:44 +00:00
|
|
|
|
G_OBJECT_CLASS (gtk_icon_theme_parent_class)->finalize (object);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_theme_set_search_path:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2020-03-02 12:42:43 +00:00
|
|
|
|
* @path: (array zero-terminated=1) (element-type filename) (nullable): NULL-terminated
|
|
|
|
|
* array of directories that are searched for icon themes
|
2020-01-30 08:12:36 +00:00
|
|
|
|
*
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* Sets the search path for the icon theme object. When looking
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* for an icon theme, GTK will search for a subdirectory of
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* one or more of the directories in @path with the same name
|
2014-06-22 20:46:11 +00:00
|
|
|
|
* as the icon theme containing an index.theme file. (Themes from
|
|
|
|
|
* multiple of the path elements are combined to allow themes to be
|
|
|
|
|
* extended by adding icons in the user’s home directory.)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
*
|
2014-02-07 18:32:47 +00:00
|
|
|
|
* In addition if an icon found isn’t found either in the current
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* icon theme or the default icon theme, and an image file with
|
|
|
|
|
* the right name is found directly in one of the elements of
|
|
|
|
|
* @path, then that image will be used for the icon name.
|
|
|
|
|
* (This is legacy feature, and new icons should be put
|
2014-06-22 20:46:11 +00:00
|
|
|
|
* into the fallback icon theme, which is called hicolor,
|
2004-01-20 16:32:54 +00:00
|
|
|
|
* rather than directly on the icon path.)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*/
|
2003-07-02 22:44:09 +00:00
|
|
|
|
void
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gtk_icon_theme_set_search_path (GtkIconTheme *self,
|
|
|
|
|
const char * const *path)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-02-18 05:56:37 +00:00
|
|
|
|
char **search_path;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_ICON_THEME (self));
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
search_path = g_strdupv ((char **)path);
|
|
|
|
|
g_strfreev (self->search_path);
|
|
|
|
|
self->search_path = search_path;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
do_theme_change (self);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_SEARCH_PATH]);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_theme_get_search_path:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2011-02-09 04:14:46 +00:00
|
|
|
|
*
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* Gets the current search path. See gtk_icon_theme_set_search_path().
|
2020-02-18 05:56:37 +00:00
|
|
|
|
*
|
2020-02-26 10:29:59 +00:00
|
|
|
|
* Returns: (transfer full) (array zero-terminated=1) (element-type filename) (nullable):
|
|
|
|
|
* a list of icon theme path directories or %NULL.
|
|
|
|
|
* The returned value should be freed with g_strfreev().
|
2011-02-09 04:14:46 +00:00
|
|
|
|
*/
|
2020-02-18 05:56:37 +00:00
|
|
|
|
char **
|
|
|
|
|
gtk_icon_theme_get_search_path (GtkIconTheme *self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-02-18 05:56:37 +00:00
|
|
|
|
char **paths;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
paths = g_strdupv (self->search_path);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
return paths;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* gtk_icon_theme_add_search_path:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2011-01-18 05:42:31 +00:00
|
|
|
|
* @path: (type filename): directory name to append to the icon path
|
2020-01-30 08:12:36 +00:00
|
|
|
|
*
|
|
|
|
|
* Appends a directory to the search path.
|
|
|
|
|
* See gtk_icon_theme_set_search_path().
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*/
|
2003-07-02 22:44:09 +00:00
|
|
|
|
void
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gtk_icon_theme_add_search_path (GtkIconTheme *self,
|
|
|
|
|
const char *path)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-02-18 05:56:37 +00:00
|
|
|
|
char **paths;
|
|
|
|
|
int len;
|
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_ICON_THEME (self));
|
2003-07-02 22:44:09 +00:00
|
|
|
|
g_return_if_fail (path != NULL);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
len = g_strv_length (self->search_path);
|
|
|
|
|
paths = g_new (char *, len + 2);
|
2020-04-14 18:43:02 +00:00
|
|
|
|
memcpy (paths, self->search_path, sizeof (char *) * len);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
paths[len] = (char *)path;
|
|
|
|
|
paths[len + 1] = NULL;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gtk_icon_theme_set_search_path (self, (const char * const *)paths);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
g_free (paths);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* gtk_icon_theme_set_resource_path:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* @path: NULL-terminated array of resource paths
|
|
|
|
|
* that are searched for icons
|
2020-01-30 08:12:36 +00:00
|
|
|
|
*
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* Sets the resource paths that will be looked at when
|
|
|
|
|
* looking for icons, similar to search paths.
|
|
|
|
|
*
|
|
|
|
|
* The resources are considered as part of the hicolor icon theme
|
|
|
|
|
* and must be located in subdirectories that are defined in the
|
2020-09-30 12:01:50 +00:00
|
|
|
|
* hicolor icon theme, such as `@path/16x16/actions/run.png`
|
|
|
|
|
* or `@path/scalable/actions/run.svg`.
|
|
|
|
|
*
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* Icons that are directly placed in the resource path instead
|
2020-09-30 12:01:50 +00:00
|
|
|
|
* of a subdirectory are also considered as ultimate fallback,
|
|
|
|
|
* but they are treated like unthemed icons.
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*/
|
2003-07-02 22:44:09 +00:00
|
|
|
|
void
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gtk_icon_theme_set_resource_path (GtkIconTheme *self,
|
|
|
|
|
const char * const *path)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-02-18 05:56:37 +00:00
|
|
|
|
char **search_path;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_ICON_THEME (self));
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
search_path = g_strdupv ((char **)path);
|
|
|
|
|
g_strfreev (self->resource_path);
|
|
|
|
|
self->resource_path = search_path;
|
|
|
|
|
|
|
|
|
|
do_theme_change (self);
|
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_RESOURCE_PATH]);
|
|
|
|
|
}
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_theme_get_resource_path:
|
|
|
|
|
* @self: a #GtkIconTheme
|
|
|
|
|
*
|
|
|
|
|
* Gets the current resource path.
|
|
|
|
|
*
|
|
|
|
|
* See gtk_icon_theme_set_resource_path().
|
|
|
|
|
*
|
2020-02-26 10:29:59 +00:00
|
|
|
|
* Returns: (transfer full) (array zero-terminated=1) (element-type utf8) (nullable):
|
|
|
|
|
* A list of resource paths or %NULL.
|
|
|
|
|
* The returned value should be freed with g_strfreev().
|
2020-02-18 05:56:37 +00:00
|
|
|
|
*/
|
|
|
|
|
char **
|
|
|
|
|
gtk_icon_theme_get_resource_path (GtkIconTheme *self)
|
|
|
|
|
{
|
|
|
|
|
char **paths;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
|
|
|
|
|
|
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
|
|
|
|
paths = g_strdupv (self->resource_path);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
return paths;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-20 04:46:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_theme_add_resource_path:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2014-06-20 04:46:09 +00:00
|
|
|
|
* @path: a resource path
|
|
|
|
|
*
|
|
|
|
|
* Adds a resource path that will be looked at when looking
|
|
|
|
|
* for icons, similar to search paths.
|
|
|
|
|
*
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* See gtk_icon_theme_set_resource_path().
|
|
|
|
|
*
|
2014-06-20 04:46:09 +00:00
|
|
|
|
* This function should be used to make application-specific icons
|
|
|
|
|
* available as part of the icon theme.
|
|
|
|
|
*/
|
2014-06-20 04:35:57 +00:00
|
|
|
|
void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
gtk_icon_theme_add_resource_path (GtkIconTheme *self,
|
2020-02-18 05:56:37 +00:00
|
|
|
|
const char *path)
|
2014-06-20 04:35:57 +00:00
|
|
|
|
{
|
2020-02-18 05:56:37 +00:00
|
|
|
|
char **paths;
|
|
|
|
|
int len;
|
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_ICON_THEME (self));
|
2014-06-20 04:35:57 +00:00
|
|
|
|
g_return_if_fail (path != NULL);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
len = g_strv_length (self->resource_path);
|
|
|
|
|
paths = g_new (char *, len + 2);
|
|
|
|
|
memcpy (paths, self->resource_path, sizeof (char *) * len);
|
|
|
|
|
paths[len] = (char *)path;
|
|
|
|
|
paths[len + 1] = NULL;
|
2014-06-20 04:35:57 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gtk_icon_theme_set_resource_path (self, (const char * const *)paths);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
g_free (paths);
|
2014-06-20 04:35:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
/**
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* gtk_icon_theme_set_theme_name:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2011-01-18 08:25:47 +00:00
|
|
|
|
* @theme_name: (allow-none): name of icon theme to use instead of
|
|
|
|
|
* configured theme, or %NULL to unset a previously set custom theme
|
2020-01-30 08:12:36 +00:00
|
|
|
|
*
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* Sets the name of the icon theme that the #GtkIconTheme object uses
|
|
|
|
|
* overriding system configuration. This function cannot be called
|
2020-02-01 22:38:49 +00:00
|
|
|
|
* on the icon theme objects returned from gtk_icon_theme_get_for_display().
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*/
|
2003-07-02 22:44:09 +00:00
|
|
|
|
void
|
2020-02-18 05:56:37 +00:00
|
|
|
|
gtk_icon_theme_set_theme_name (GtkIconTheme *self,
|
|
|
|
|
const char *theme_name)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_ICON_THEME (self));
|
|
|
|
|
g_return_if_fail (!self->is_display_singleton);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
if (theme_name != NULL)
|
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->custom_theme = TRUE;
|
|
|
|
|
if (!self->current_theme || strcmp (theme_name, self->current_theme) != 0)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_free (self->current_theme);
|
|
|
|
|
self->current_theme = g_strdup (theme_name);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
do_theme_change (self);
|
2014-06-19 23:42:53 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (self->custom_theme)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->custom_theme = FALSE;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
update_current_theme__mainthread (self);
|
2014-06-19 23:42:53 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
2020-02-18 05:56:37 +00:00
|
|
|
|
|
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_THEME_NAME]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_theme_get_theme_name:
|
|
|
|
|
* @self: a #GtkIconTheme
|
|
|
|
|
*
|
|
|
|
|
* Gets the current icon theme name.
|
|
|
|
|
*
|
|
|
|
|
* Returns (transfer full): the current icon theme name,
|
|
|
|
|
*/
|
|
|
|
|
char *
|
|
|
|
|
gtk_icon_theme_get_theme_name (GtkIconTheme *self)
|
|
|
|
|
{
|
|
|
|
|
char *theme_name;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
|
|
|
|
|
|
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
|
|
|
|
if (self->custom_theme)
|
|
|
|
|
theme_name = g_strdup (self->current_theme);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (self->display)
|
|
|
|
|
{
|
|
|
|
|
GtkSettings *settings = gtk_settings_get_for_display (self->display);
|
|
|
|
|
g_object_get (settings, "gtk-icon-theme-name", &theme_name, NULL);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
theme_name = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
|
|
|
|
|
|
|
|
|
return theme_name;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-24 18:40:36 +00:00
|
|
|
|
static const char builtin_hicolor_index[] =
|
2014-06-20 05:04:16 +00:00
|
|
|
|
"[Icon Theme]\n"
|
|
|
|
|
"Name=Hicolor\n"
|
|
|
|
|
"Hidden=True\n"
|
2016-03-31 11:11:24 +00:00
|
|
|
|
"Directories=16x16/actions,16x16/status,22x22/actions,24x24/actions,24x24/status,32x32/actions,32x32/status,48x48/status,64x64/actions\n"
|
2014-06-20 05:04:16 +00:00
|
|
|
|
"[16x16/actions]\n"
|
|
|
|
|
"Size=16\n"
|
|
|
|
|
"Type=Threshold\n"
|
2016-03-31 11:11:24 +00:00
|
|
|
|
"[16x16/status]\n"
|
|
|
|
|
"Size=16\n"
|
|
|
|
|
"Type=Threshold\n"
|
2014-06-20 05:04:16 +00:00
|
|
|
|
"[22x22/actions]\n"
|
|
|
|
|
"Size=22\n"
|
|
|
|
|
"Type=Threshold\n"
|
|
|
|
|
"[24x24/actions]\n"
|
|
|
|
|
"Size=24\n"
|
|
|
|
|
"Type=Threshold\n"
|
2016-03-31 11:11:24 +00:00
|
|
|
|
"[24x24/status]\n"
|
|
|
|
|
"Size=24\n"
|
|
|
|
|
"Type=Threshold\n"
|
2014-06-20 05:04:16 +00:00
|
|
|
|
"[32x32/actions]\n"
|
|
|
|
|
"Size=32\n"
|
2016-03-31 11:11:24 +00:00
|
|
|
|
"Type=Threshold\n"
|
|
|
|
|
"[32x32/status]\n"
|
|
|
|
|
"Size=32\n"
|
|
|
|
|
"Type=Threshold\n"
|
|
|
|
|
"[48x48/status]\n"
|
|
|
|
|
"Size=48\n"
|
|
|
|
|
"Type=Threshold\n"
|
|
|
|
|
"[64x64/actions]\n"
|
|
|
|
|
"Size=64\n"
|
2014-06-20 05:04:16 +00:00
|
|
|
|
"Type=Threshold\n";
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
static void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
insert_theme (GtkIconTheme *self,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *theme_name)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int i;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
GList *l;
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char **dirs;
|
|
|
|
|
char **scaled_dirs;
|
|
|
|
|
char **themes;
|
2006-10-08 05:07:55 +00:00
|
|
|
|
IconTheme *theme = NULL;
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *path;
|
2004-10-24 05:48:16 +00:00
|
|
|
|
GKeyFile *theme_file;
|
|
|
|
|
GError *error = NULL;
|
2011-10-03 15:25:33 +00:00
|
|
|
|
GStatBuf stat_buf;
|
2004-10-19 18:45:41 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
for (l = self->themes; l != NULL; l = l->next)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
theme = l->data;
|
|
|
|
|
if (strcmp (theme->name, theme_name) == 0)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
return;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
for (i = 0; self->search_path[i]; i++)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-04-25 18:18:29 +00:00
|
|
|
|
IconThemeDirMtime dir_mtime;
|
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
path = g_build_filename (self->search_path[i], theme_name, NULL);
|
2020-04-25 18:18:29 +00:00
|
|
|
|
dir_mtime.cache = NULL;
|
|
|
|
|
dir_mtime.dir = path;
|
2020-02-18 05:56:37 +00:00
|
|
|
|
if (g_stat (path, &stat_buf) == 0 && S_ISDIR (stat_buf.st_mode))
|
|
|
|
|
{
|
2020-04-25 18:18:29 +00:00
|
|
|
|
dir_mtime.mtime = stat_buf.st_mtime;
|
|
|
|
|
dir_mtime.exists = TRUE;
|
2020-02-18 05:56:37 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-04-25 18:18:29 +00:00
|
|
|
|
dir_mtime.mtime = 0;
|
|
|
|
|
dir_mtime.exists = FALSE;
|
2020-02-18 05:56:37 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-04-25 18:18:29 +00:00
|
|
|
|
g_array_insert_val (self->dir_mtimes, 0, dir_mtime);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
theme_file = NULL;
|
2020-02-18 05:56:37 +00:00
|
|
|
|
for (i = 0; self->search_path[i] && !theme_file; i++)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-02-18 05:56:37 +00:00
|
|
|
|
path = g_build_filename (self->search_path[i], theme_name, "index.theme", NULL);
|
2020-01-30 08:12:36 +00:00
|
|
|
|
if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
|
|
|
|
theme_file = g_key_file_new ();
|
|
|
|
|
g_key_file_set_list_separator (theme_file, ',');
|
2015-07-17 19:54:40 +00:00
|
|
|
|
if (!g_key_file_load_from_file (theme_file, path, 0, &error))
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
|
|
|
|
g_key_file_free (theme_file);
|
|
|
|
|
theme_file = NULL;
|
|
|
|
|
g_error_free (error);
|
|
|
|
|
error = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
g_free (path);
|
|
|
|
|
}
|
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (theme_file == NULL)
|
2005-11-12 06:59:49 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (strcmp (theme_name, FALLBACK_ICON_THEME) == 0)
|
2014-06-20 05:04:16 +00:00
|
|
|
|
{
|
|
|
|
|
theme_file = g_key_file_new ();
|
|
|
|
|
g_key_file_set_list_separator (theme_file, ',');
|
|
|
|
|
g_key_file_load_from_data (theme_file, builtin_hicolor_index, -1, 0, NULL);
|
|
|
|
|
}
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
else
|
|
|
|
|
return;
|
2005-11-12 06:59:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-10-24 05:48:16 +00:00
|
|
|
|
dirs = g_key_file_get_string_list (theme_file, "Icon Theme", "Directories", NULL, NULL);
|
|
|
|
|
if (!dirs)
|
2006-04-12 04:22:51 +00:00
|
|
|
|
{
|
2016-02-28 16:06:25 +00:00
|
|
|
|
g_warning ("Theme file for %s has no directories", theme_name);
|
2006-04-12 04:22:51 +00:00
|
|
|
|
g_key_file_free (theme_file);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-08-19 13:42:30 +00:00
|
|
|
|
|
|
|
|
|
scaled_dirs = g_key_file_get_string_list (theme_file, "Icon Theme", "ScaledDirectories", NULL, NULL);
|
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
theme = theme_new (theme_name, theme_file);
|
|
|
|
|
self->themes = g_list_prepend (self->themes, theme);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2006-04-12 04:22:51 +00:00
|
|
|
|
for (i = 0; dirs[i] != NULL; i++)
|
2019-09-08 12:57:40 +00:00
|
|
|
|
theme_subdir_load (self, theme, theme_file, dirs[i]);
|
2006-04-12 04:22:51 +00:00
|
|
|
|
|
2013-08-19 13:42:30 +00:00
|
|
|
|
if (scaled_dirs)
|
|
|
|
|
{
|
|
|
|
|
for (i = 0; scaled_dirs[i] != NULL; i++)
|
2019-09-08 12:57:40 +00:00
|
|
|
|
theme_subdir_load (self, theme, theme_file, scaled_dirs[i]);
|
2013-08-19 13:42:30 +00:00
|
|
|
|
}
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
2006-04-12 04:22:51 +00:00
|
|
|
|
g_strfreev (dirs);
|
2013-08-19 13:42:30 +00:00
|
|
|
|
g_strfreev (scaled_dirs);
|
2006-04-12 04:22:51 +00:00
|
|
|
|
|
2004-10-24 05:48:16 +00:00
|
|
|
|
themes = g_key_file_get_string_list (theme_file,
|
2014-06-19 23:42:53 +00:00
|
|
|
|
"Icon Theme",
|
|
|
|
|
"Inherits",
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
2004-10-24 05:48:16 +00:00
|
|
|
|
if (themes)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
for (i = 0; themes[i] != NULL; i++)
|
2019-09-08 12:57:40 +00:00
|
|
|
|
insert_theme (self, themes[i]);
|
2020-01-28 14:43:51 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
g_strfreev (themes);
|
|
|
|
|
}
|
|
|
|
|
|
2004-10-24 05:48:16 +00:00
|
|
|
|
g_key_file_free (theme_file);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_unthemed_icon (UnthemedIcon *unthemed_icon)
|
|
|
|
|
{
|
2007-03-09 21:57:37 +00:00
|
|
|
|
g_free (unthemed_icon->svg_filename);
|
|
|
|
|
g_free (unthemed_icon->no_svg_filename);
|
2006-03-31 05:17:56 +00:00
|
|
|
|
g_slice_free (UnthemedIcon, unthemed_icon);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
static void
|
|
|
|
|
strip_suffix_inline (char *filename)
|
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *dot;
|
2020-02-07 10:54:00 +00:00
|
|
|
|
|
|
|
|
|
if (g_str_has_suffix (filename, ".symbolic.png"))
|
|
|
|
|
filename[strlen(filename)-13] = 0;
|
|
|
|
|
|
|
|
|
|
dot = strrchr (filename, '.');
|
|
|
|
|
|
|
|
|
|
if (dot != NULL)
|
|
|
|
|
*dot = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-24 18:40:36 +00:00
|
|
|
|
static char *
|
|
|
|
|
strip_suffix (const char *filename)
|
2006-04-18 13:58:30 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *dot;
|
2006-04-18 13:58:30 +00:00
|
|
|
|
|
2014-07-30 16:05:48 +00:00
|
|
|
|
if (g_str_has_suffix (filename, ".symbolic.png"))
|
|
|
|
|
return g_strndup (filename, strlen(filename)-13);
|
|
|
|
|
|
2006-04-18 13:58:30 +00:00
|
|
|
|
dot = strrchr (filename, '.');
|
|
|
|
|
|
|
|
|
|
if (dot == NULL)
|
|
|
|
|
return g_strdup (filename);
|
|
|
|
|
|
|
|
|
|
return g_strndup (filename, dot - filename);
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-30 21:02:41 +00:00
|
|
|
|
static void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
add_unthemed_icon (GtkIconTheme *self,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *dir,
|
|
|
|
|
const char *file,
|
2014-06-30 21:02:41 +00:00
|
|
|
|
gboolean is_resource)
|
|
|
|
|
{
|
2020-02-04 08:35:20 +00:00
|
|
|
|
IconCacheFlag new_suffix, old_suffix;
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *abs_file;
|
|
|
|
|
char *base_name;
|
2014-06-30 21:02:41 +00:00
|
|
|
|
UnthemedIcon *unthemed_icon;
|
|
|
|
|
|
|
|
|
|
new_suffix = suffix_from_name (file);
|
|
|
|
|
|
2020-02-04 08:35:20 +00:00
|
|
|
|
if (new_suffix == ICON_CACHE_FLAG_NONE)
|
2014-06-30 21:02:41 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
abs_file = g_build_filename (dir, file, NULL);
|
|
|
|
|
base_name = strip_suffix (file);
|
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
unthemed_icon = g_hash_table_lookup (self->unthemed_icons, base_name);
|
2014-06-30 21:02:41 +00:00
|
|
|
|
|
|
|
|
|
if (unthemed_icon)
|
|
|
|
|
{
|
2020-02-04 08:35:20 +00:00
|
|
|
|
if (new_suffix == ICON_CACHE_FLAG_SVG_SUFFIX)
|
2014-06-30 21:02:41 +00:00
|
|
|
|
{
|
|
|
|
|
if (unthemed_icon->svg_filename)
|
|
|
|
|
g_free (abs_file);
|
|
|
|
|
else
|
|
|
|
|
unthemed_icon->svg_filename = abs_file;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (unthemed_icon->no_svg_filename)
|
|
|
|
|
{
|
|
|
|
|
old_suffix = suffix_from_name (unthemed_icon->no_svg_filename);
|
|
|
|
|
if (new_suffix > old_suffix)
|
|
|
|
|
{
|
|
|
|
|
g_free (unthemed_icon->no_svg_filename);
|
|
|
|
|
unthemed_icon->no_svg_filename = abs_file;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
g_free (abs_file);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
unthemed_icon->no_svg_filename = abs_file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (base_name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unthemed_icon = g_slice_new0 (UnthemedIcon);
|
|
|
|
|
|
|
|
|
|
unthemed_icon->is_resource = is_resource;
|
|
|
|
|
|
2020-02-04 08:35:20 +00:00
|
|
|
|
if (new_suffix == ICON_CACHE_FLAG_SVG_SUFFIX)
|
2014-06-30 21:02:41 +00:00
|
|
|
|
unthemed_icon->svg_filename = abs_file;
|
|
|
|
|
else
|
|
|
|
|
unthemed_icon->no_svg_filename = abs_file;
|
|
|
|
|
|
|
|
|
|
/* takes ownership of base_name */
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_hash_table_replace (self->unthemed_icons, base_name, unthemed_icon);
|
2014-06-30 21:02:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
static void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
load_themes (GtkIconTheme *self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
GDir *gdir;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int base;
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *dir;
|
|
|
|
|
const char *file;
|
2011-10-03 15:25:33 +00:00
|
|
|
|
GStatBuf stat_buf;
|
2020-02-18 05:56:37 +00:00
|
|
|
|
int j;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (self->current_theme)
|
|
|
|
|
insert_theme (self, self->current_theme);
|
2006-01-11 06:20:17 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
insert_theme (self, FALLBACK_ICON_THEME);
|
|
|
|
|
self->themes = g_list_reverse (self->themes);
|
2004-10-19 18:45:41 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->unthemed_icons = g_hash_table_new_full (g_str_hash, g_str_equal,
|
2014-06-19 23:42:53 +00:00
|
|
|
|
g_free, (GDestroyNotify)free_unthemed_icon);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
for (base = 0; self->search_path[base]; base++)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-04-25 18:18:29 +00:00
|
|
|
|
IconThemeDirMtime *dir_mtime;
|
2019-09-08 12:57:40 +00:00
|
|
|
|
dir = self->search_path[base];
|
2004-10-19 18:45:41 +00:00
|
|
|
|
|
2020-04-25 18:18:29 +00:00
|
|
|
|
g_array_set_size (self->dir_mtimes, self->dir_mtimes->len + 1);
|
|
|
|
|
dir_mtime = &g_array_index (self->dir_mtimes, IconThemeDirMtime, self->dir_mtimes->len - 1);
|
2020-01-28 14:43:51 +00:00
|
|
|
|
|
2007-01-02 04:19:28 +00:00
|
|
|
|
dir_mtime->dir = g_strdup (dir);
|
|
|
|
|
dir_mtime->mtime = 0;
|
2015-02-23 20:49:08 +00:00
|
|
|
|
dir_mtime->exists = FALSE;
|
2007-01-02 04:19:28 +00:00
|
|
|
|
dir_mtime->cache = NULL;
|
|
|
|
|
|
|
|
|
|
if (g_stat (dir, &stat_buf) != 0 || !S_ISDIR (stat_buf.st_mode))
|
2014-06-19 23:42:53 +00:00
|
|
|
|
continue;
|
2007-01-02 04:19:28 +00:00
|
|
|
|
dir_mtime->mtime = stat_buf.st_mtime;
|
2015-02-23 20:49:08 +00:00
|
|
|
|
dir_mtime->exists = TRUE;
|
2007-01-02 04:19:28 +00:00
|
|
|
|
|
2018-02-01 15:05:58 +00:00
|
|
|
|
dir_mtime->cache = gtk_icon_cache_new_for_path (dir);
|
2005-07-13 14:07:10 +00:00
|
|
|
|
if (dir_mtime->cache != NULL)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
continue;
|
2004-10-19 18:45:41 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
gdir = g_dir_open (dir, 0, NULL);
|
|
|
|
|
if (gdir == NULL)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
continue;
|
2006-03-31 05:17:56 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
while ((file = g_dir_read_name (gdir)))
|
2019-09-08 12:57:40 +00:00
|
|
|
|
add_unthemed_icon (self, dir, file, FALSE);
|
2014-06-19 23:42:53 +00:00
|
|
|
|
|
2014-06-30 21:02:41 +00:00
|
|
|
|
g_dir_close (gdir);
|
|
|
|
|
}
|
2014-06-19 23:42:53 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
for (j = 0; self->resource_path[j]; j++)
|
2014-06-30 21:02:41 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char **children;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int i;
|
2014-06-19 23:42:53 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
dir = self->resource_path[j];
|
2014-06-30 21:02:41 +00:00
|
|
|
|
children = g_resources_enumerate_children (dir, 0, NULL);
|
|
|
|
|
if (!children)
|
|
|
|
|
continue;
|
2014-06-19 23:42:53 +00:00
|
|
|
|
|
2014-06-30 21:02:41 +00:00
|
|
|
|
for (i = 0; children[i]; i++)
|
2019-09-08 12:57:40 +00:00
|
|
|
|
add_unthemed_icon (self, dir, children[i], TRUE);
|
2014-06-19 23:42:53 +00:00
|
|
|
|
|
2014-06-30 21:02:41 +00:00
|
|
|
|
g_strfreev (children);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
self->themes_valid = TRUE;
|
2020-01-28 14:43:51 +00:00
|
|
|
|
|
2020-07-31 15:22:16 +00:00
|
|
|
|
self->last_stat_time = g_get_monotonic_time ();
|
2014-05-24 15:01:27 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
GTK_DISPLAY_NOTE (self->display, ICONTHEME, {
|
2014-05-24 15:01:27 +00:00
|
|
|
|
GList *l;
|
2016-02-28 20:33:18 +00:00
|
|
|
|
GString *s;
|
|
|
|
|
s = g_string_new ("Current icon themes ");
|
2019-09-08 12:57:40 +00:00
|
|
|
|
for (l = self->themes; l; l = l->next)
|
2014-05-24 15:01:27 +00:00
|
|
|
|
{
|
|
|
|
|
IconTheme *theme = l->data;
|
2016-02-28 20:33:18 +00:00
|
|
|
|
g_string_append (s, theme->name);
|
|
|
|
|
g_string_append_c (s, ' ');
|
2014-05-24 15:01:27 +00:00
|
|
|
|
}
|
2016-02-28 20:33:18 +00:00
|
|
|
|
g_message ("%s", s->str);
|
|
|
|
|
g_string_free (s, TRUE);
|
2014-05-24 15:01:27 +00:00
|
|
|
|
});
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-28 12:47:59 +00:00
|
|
|
|
static gboolean
|
2020-01-28 14:43:51 +00:00
|
|
|
|
ensure_valid_themes (GtkIconTheme *self,
|
2020-01-30 11:27:15 +00:00
|
|
|
|
gboolean non_blocking)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
gboolean was_valid = self->themes_valid;
|
2005-08-22 20:12:15 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (self->themes_valid)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-07-31 15:22:16 +00:00
|
|
|
|
gint64 now = g_get_monotonic_time ();
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-07-31 15:22:16 +00:00
|
|
|
|
if ((now - self->last_stat_time) / G_USEC_PER_SEC > 5)
|
2013-06-19 07:35:24 +00:00
|
|
|
|
{
|
2020-01-28 12:47:59 +00:00
|
|
|
|
if (non_blocking)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (rescan_themes (self))
|
|
|
|
|
{
|
2020-01-29 10:08:02 +00:00
|
|
|
|
icon_cache_clear (self);
|
2020-01-28 12:47:59 +00:00
|
|
|
|
blow_themes (self);
|
|
|
|
|
}
|
2013-06-19 07:35:24 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2019-09-01 11:25:44 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
if (!self->themes_valid)
|
2005-08-22 20:12:15 +00:00
|
|
|
|
{
|
2020-08-19 22:49:34 +00:00
|
|
|
|
gint64 before G_GNUC_UNUSED;
|
|
|
|
|
|
2020-01-28 12:47:59 +00:00
|
|
|
|
if (non_blocking)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2020-08-19 22:49:34 +00:00
|
|
|
|
before = GDK_PROFILER_CURRENT_TIME;
|
2020-01-28 16:08:52 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
load_themes (self);
|
2005-08-22 20:12:15 +00:00
|
|
|
|
|
2020-08-19 22:49:34 +00:00
|
|
|
|
gdk_profiler_end_mark (before, "icon theme load", self->current_theme);
|
2020-01-28 16:08:52 +00:00
|
|
|
|
|
2007-03-15 18:40:16 +00:00
|
|
|
|
if (was_valid)
|
2019-09-08 12:57:40 +00:00
|
|
|
|
queue_theme_changed (self);
|
2005-08-22 20:12:15 +00:00
|
|
|
|
}
|
2007-03-15 18:40:16 +00:00
|
|
|
|
|
2020-01-28 12:47:59 +00:00
|
|
|
|
return TRUE;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-21 12:26:19 +00:00
|
|
|
|
static inline gboolean
|
2020-07-24 18:40:36 +00:00
|
|
|
|
icon_name_is_symbolic (const char *icon_name,
|
2019-05-21 12:26:19 +00:00
|
|
|
|
int icon_name_len)
|
2014-05-13 13:50:05 +00:00
|
|
|
|
{
|
2019-05-21 12:26:19 +00:00
|
|
|
|
|
|
|
|
|
if (icon_name_len < 0)
|
|
|
|
|
icon_name_len = strlen (icon_name);
|
|
|
|
|
|
|
|
|
|
if (icon_name_len > strlen ("-symbolic"))
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (icon_name + icon_name_len - strlen ("-symbolic"), "-symbolic") == 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (icon_name_len > strlen ("-symbolic-ltr"))
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (icon_name + icon_name_len - strlen ("-symbolic-ltr"), "-symbolic-ltr") == 0 ||
|
|
|
|
|
strcmp (icon_name + icon_name_len - strlen ("-symbolic-rtl"), "-symbolic-rtl") == 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2014-05-13 13:50:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-28 08:14:52 +00:00
|
|
|
|
static inline gboolean
|
2020-07-24 18:40:36 +00:00
|
|
|
|
icon_uri_is_symbolic (const char *icon_name,
|
2019-05-28 08:14:52 +00:00
|
|
|
|
int icon_name_len)
|
2014-05-13 13:50:05 +00:00
|
|
|
|
{
|
2019-05-28 08:14:52 +00:00
|
|
|
|
if (icon_name_len < 0)
|
|
|
|
|
icon_name_len = strlen (icon_name);
|
|
|
|
|
|
|
|
|
|
if (icon_name_len > strlen ("-symbolic.svg"))
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (icon_name + icon_name_len - strlen ("-symbolic.svg"), "-symbolic.svg") == 0 ||
|
|
|
|
|
strcmp (icon_name + icon_name_len - strlen (".symbolic.png"), ".symbolic.png") == 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (icon_name_len > strlen ("-symbolic-ltr.svg"))
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (icon_name + icon_name_len - strlen ("-symbolic.ltr.svg"), "-symbolic-ltr.svg") == 0 ||
|
|
|
|
|
strcmp (icon_name + icon_name_len - strlen ("-symbolic.rtl.svg"), "-symbolic-rtl.svg") == 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2014-05-13 13:50:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
static GtkIconPaintable *
|
2020-01-30 11:27:15 +00:00
|
|
|
|
real_choose_icon (GtkIconTheme *self,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *icon_names[],
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size,
|
|
|
|
|
int scale,
|
2020-01-30 11:27:15 +00:00
|
|
|
|
GtkIconLookupFlags flags,
|
2020-03-05 06:56:01 +00:00
|
|
|
|
gboolean non_blocking)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
GList *l;
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon = NULL;
|
2007-06-03 20:44:10 +00:00
|
|
|
|
UnthemedIcon *unthemed_icon = NULL;
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *icon_name = NULL;
|
2013-09-23 10:42:30 +00:00
|
|
|
|
IconTheme *theme = NULL;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int i;
|
2020-01-30 09:52:09 +00:00
|
|
|
|
IconKey key;
|
2004-10-20 17:23:02 +00:00
|
|
|
|
|
2020-01-28 12:47:59 +00:00
|
|
|
|
if (!ensure_valid_themes (self, non_blocking))
|
2020-03-05 06:56:01 +00:00
|
|
|
|
return NULL;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2020-07-24 18:40:36 +00:00
|
|
|
|
key.icon_names = (char **)icon_names;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
key.size = size;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
key.scale = scale;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
key.flags = flags;
|
|
|
|
|
|
2014-05-14 02:13:58 +00:00
|
|
|
|
/* This is used in the icontheme unit test */
|
2019-09-08 12:57:40 +00:00
|
|
|
|
GTK_DISPLAY_NOTE (self->display, ICONTHEME,
|
2014-05-14 02:13:58 +00:00
|
|
|
|
for (i = 0; icon_names[i]; i++)
|
2016-02-28 20:33:18 +00:00
|
|
|
|
g_message ("\tlookup name: %s", icon_names[i]));
|
2014-05-14 02:13:58 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
icon = icon_cache_lookup (self, &key);
|
|
|
|
|
if (icon)
|
|
|
|
|
return icon;
|
|
|
|
|
|
2014-09-21 18:46:09 +00:00
|
|
|
|
/* For symbolic icons, do a search in all registered themes first;
|
2012-04-25 01:47:33 +00:00
|
|
|
|
* a theme that inherits them from a parent theme might provide
|
2014-09-21 18:29:36 +00:00
|
|
|
|
* an alternative full-color version, but still expect the symbolic icon
|
2012-04-25 01:47:33 +00:00
|
|
|
|
* to show up instead.
|
2014-09-21 18:46:09 +00:00
|
|
|
|
*
|
|
|
|
|
* In other words: We prefer symbolic icons in inherited themes over
|
|
|
|
|
* generic icons in the theme.
|
2012-04-25 01:47:33 +00:00
|
|
|
|
*/
|
2019-09-08 12:57:40 +00:00
|
|
|
|
for (l = self->themes; l; l = l->next)
|
2012-04-25 01:47:33 +00:00
|
|
|
|
{
|
2014-09-21 18:46:09 +00:00
|
|
|
|
theme = l->data;
|
2019-05-21 12:26:19 +00:00
|
|
|
|
for (i = 0; icon_names[i] && icon_name_is_symbolic (icon_names[i], -1); i++)
|
2012-04-25 01:47:33 +00:00
|
|
|
|
{
|
2014-09-21 18:46:09 +00:00
|
|
|
|
icon_name = icon_names[i];
|
2020-02-01 23:42:43 +00:00
|
|
|
|
icon = theme_lookup_icon (theme, icon_name, size, scale, self->pixbuf_supports_svg);
|
2020-01-28 14:43:51 +00:00
|
|
|
|
if (icon)
|
2012-04-25 01:47:33 +00:00
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
for (l = self->themes; l; l = l->next)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2013-09-23 10:42:30 +00:00
|
|
|
|
theme = l->data;
|
|
|
|
|
|
2007-05-18 20:19:12 +00:00
|
|
|
|
for (i = 0; icon_names[i]; i++)
|
2007-04-19 04:14:39 +00:00
|
|
|
|
{
|
2013-09-23 10:42:30 +00:00
|
|
|
|
icon_name = icon_names[i];
|
2020-02-01 23:42:43 +00:00
|
|
|
|
icon = theme_lookup_icon (theme, icon_name, size, scale, self->pixbuf_supports_svg);
|
2020-01-28 14:43:51 +00:00
|
|
|
|
if (icon)
|
2007-05-18 20:19:12 +00:00
|
|
|
|
goto out;
|
2007-04-19 04:14:39 +00:00
|
|
|
|
}
|
2007-05-18 20:19:12 +00:00
|
|
|
|
}
|
2007-04-19 04:14:39 +00:00
|
|
|
|
|
2013-09-23 10:42:30 +00:00
|
|
|
|
theme = NULL;
|
|
|
|
|
|
2007-05-18 20:19:12 +00:00
|
|
|
|
for (i = 0; icon_names[i]; i++)
|
|
|
|
|
{
|
2019-09-08 12:57:40 +00:00
|
|
|
|
unthemed_icon = g_hash_table_lookup (self->unthemed_icons, icon_names[i]);
|
2007-05-18 20:19:12 +00:00
|
|
|
|
if (unthemed_icon)
|
2020-02-05 16:08:29 +00:00
|
|
|
|
{
|
2020-02-10 10:40:00 +00:00
|
|
|
|
icon = icon_paintable_new (icon_names[i], size, scale);
|
2020-02-05 16:08:29 +00:00
|
|
|
|
|
|
|
|
|
/* A SVG icon, when allowed, beats out a XPM icon, but not a PNG icon */
|
|
|
|
|
if (self->pixbuf_supports_svg &&
|
|
|
|
|
unthemed_icon->svg_filename &&
|
|
|
|
|
(!unthemed_icon->no_svg_filename ||
|
|
|
|
|
suffix_from_name (unthemed_icon->no_svg_filename) < ICON_CACHE_FLAG_PNG_SUFFIX))
|
|
|
|
|
icon->filename = g_strdup (unthemed_icon->svg_filename);
|
|
|
|
|
else if (unthemed_icon->no_svg_filename)
|
|
|
|
|
icon->filename = g_strdup (unthemed_icon->no_svg_filename);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
g_clear_object (&icon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (icon)
|
2020-03-05 05:57:44 +00:00
|
|
|
|
{
|
|
|
|
|
icon->is_svg = suffix_from_name (icon->filename) == ICON_CACHE_FLAG_SVG_SUFFIX;
|
|
|
|
|
icon->is_resource = unthemed_icon->is_resource;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2020-02-05 16:08:29 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2020-02-05 16:08:29 +00:00
|
|
|
|
|
2008-06-16 13:27:46 +00:00
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
/* Still not found an icon, check if reference to a Win32 resource */
|
2020-02-05 16:08:29 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char **resources;
|
2008-06-16 13:27:46 +00:00
|
|
|
|
HICON hIcon = NULL;
|
2020-01-28 14:43:51 +00:00
|
|
|
|
|
2008-06-16 13:27:46 +00:00
|
|
|
|
resources = g_strsplit (icon_names[0], ",", 0);
|
|
|
|
|
if (resources[0])
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
|
|
|
|
wchar_t *wfile = g_utf8_to_utf16 (resources[0], -1, NULL, NULL, NULL);
|
|
|
|
|
ExtractIconExW (wfile, resources[1] ? atoi (resources[1]) : 0, &hIcon, NULL, 1);
|
|
|
|
|
g_free (wfile);
|
|
|
|
|
}
|
2020-01-28 14:43:51 +00:00
|
|
|
|
|
2008-06-16 13:27:46 +00:00
|
|
|
|
if (hIcon)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
2020-02-10 10:40:00 +00:00
|
|
|
|
icon = icon_paintable_new (resources[0], size, scale);
|
2020-02-05 16:08:29 +00:00
|
|
|
|
icon->win32_icon = gdk_win32_icon_to_pixbuf_libgtk_only (hIcon, NULL, NULL);
|
2014-06-19 23:42:53 +00:00
|
|
|
|
DestroyIcon (hIcon);
|
2020-02-05 16:08:29 +00:00
|
|
|
|
goto out;
|
2014-06-19 23:42:53 +00:00
|
|
|
|
}
|
2008-06-16 13:27:46 +00:00
|
|
|
|
g_strfreev (resources);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
|
|
|
|
|
/* Fall back to missing icon */
|
|
|
|
|
if (icon == NULL)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-02-10 10:40:00 +00:00
|
|
|
|
icon = icon_paintable_new ("image-missing", size, scale);
|
2020-02-05 16:08:29 +00:00
|
|
|
|
icon->filename = g_strdup (IMAGE_MISSING_RESOURCE_PATH);
|
|
|
|
|
icon->is_resource = TRUE;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
2020-02-05 16:08:29 +00:00
|
|
|
|
g_assert (icon != NULL);
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
icon->key.icon_names = g_strdupv ((char **)icon_names);
|
|
|
|
|
icon->key.size = size;
|
|
|
|
|
icon->key.scale = scale;
|
|
|
|
|
icon->key.flags = flags;
|
2020-01-29 10:08:02 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
icon_cache_add (self, icon);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
return icon;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-05-14 01:34:49 +00:00
|
|
|
|
static void
|
2020-07-03 02:21:07 +00:00
|
|
|
|
icon_name_list_add_icon (GtkStrvBuilder *icons,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *dir_suffix,
|
|
|
|
|
char *icon_name)
|
2014-05-14 01:34:49 +00:00
|
|
|
|
{
|
|
|
|
|
if (dir_suffix)
|
2020-07-03 02:21:07 +00:00
|
|
|
|
gtk_strv_builder_append (icons, g_strconcat (icon_name, dir_suffix, NULL));
|
|
|
|
|
gtk_strv_builder_append (icons, icon_name);
|
2014-05-14 01:34:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
static GtkIconPaintable *
|
2020-01-30 11:27:15 +00:00
|
|
|
|
choose_icon (GtkIconTheme *self,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *icon_names[],
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size,
|
|
|
|
|
int scale,
|
2020-02-01 23:27:14 +00:00
|
|
|
|
GtkTextDirection direction,
|
2020-01-30 11:27:15 +00:00
|
|
|
|
GtkIconLookupFlags flags,
|
2020-03-05 06:56:01 +00:00
|
|
|
|
gboolean non_blocking)
|
2014-05-10 13:35:12 +00:00
|
|
|
|
{
|
|
|
|
|
gboolean has_regular = FALSE, has_symbolic = FALSE;
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon;
|
2020-07-03 02:21:07 +00:00
|
|
|
|
GtkStrvBuilder new_names;
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *dir_suffix;
|
2014-05-10 13:35:12 +00:00
|
|
|
|
guint i;
|
|
|
|
|
|
2020-02-01 23:27:14 +00:00
|
|
|
|
switch (direction)
|
|
|
|
|
{
|
|
|
|
|
case GTK_TEXT_DIR_NONE:
|
|
|
|
|
dir_suffix = NULL;
|
|
|
|
|
break;
|
|
|
|
|
case GTK_TEXT_DIR_LTR:
|
2014-05-14 01:34:49 +00:00
|
|
|
|
dir_suffix = "-ltr";
|
2020-02-01 23:27:14 +00:00
|
|
|
|
break;
|
|
|
|
|
case GTK_TEXT_DIR_RTL:
|
2014-05-14 01:34:49 +00:00
|
|
|
|
dir_suffix = "-rtl";
|
2020-02-01 23:27:14 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached();
|
2014-05-14 01:34:49 +00:00
|
|
|
|
dir_suffix = NULL;
|
2020-02-01 23:27:14 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2014-05-14 01:34:49 +00:00
|
|
|
|
|
2014-05-10 13:35:12 +00:00
|
|
|
|
for (i = 0; icon_names[i]; i++)
|
|
|
|
|
{
|
2019-05-21 12:26:19 +00:00
|
|
|
|
if (icon_name_is_symbolic (icon_names[i], -1))
|
2014-05-10 13:35:12 +00:00
|
|
|
|
has_symbolic = TRUE;
|
|
|
|
|
else
|
|
|
|
|
has_regular = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((flags & GTK_ICON_LOOKUP_FORCE_REGULAR) && has_symbolic)
|
|
|
|
|
{
|
2020-07-03 02:21:07 +00:00
|
|
|
|
gtk_strv_builder_init (&new_names);
|
2014-05-10 13:35:12 +00:00
|
|
|
|
for (i = 0; icon_names[i]; i++)
|
|
|
|
|
{
|
2019-05-21 12:26:19 +00:00
|
|
|
|
if (icon_name_is_symbolic (icon_names[i], -1))
|
2020-07-03 02:21:07 +00:00
|
|
|
|
icon_name_list_add_icon (&new_names, dir_suffix, g_strndup (icon_names[i], strlen (icon_names[i]) - strlen ("-symbolic")));
|
2014-05-10 13:35:12 +00:00
|
|
|
|
else
|
2020-07-03 02:21:07 +00:00
|
|
|
|
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
2014-05-10 13:35:12 +00:00
|
|
|
|
}
|
2014-05-11 00:30:50 +00:00
|
|
|
|
for (i = 0; icon_names[i]; i++)
|
|
|
|
|
{
|
2019-05-21 12:26:19 +00:00
|
|
|
|
if (icon_name_is_symbolic (icon_names[i], -1))
|
2020-07-03 02:21:07 +00:00
|
|
|
|
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
2014-05-11 00:30:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon = real_choose_icon (self,
|
2020-07-03 02:21:07 +00:00
|
|
|
|
(const char **) gtk_strv_builder_get_data (&new_names),
|
2020-01-30 11:27:15 +00:00
|
|
|
|
size,
|
|
|
|
|
scale,
|
|
|
|
|
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
|
2020-03-05 06:56:01 +00:00
|
|
|
|
non_blocking);
|
2014-05-11 00:30:50 +00:00
|
|
|
|
|
2020-07-03 02:21:07 +00:00
|
|
|
|
gtk_strv_builder_clear (&new_names);
|
2014-05-10 13:35:12 +00:00
|
|
|
|
}
|
|
|
|
|
else if ((flags & GTK_ICON_LOOKUP_FORCE_SYMBOLIC) && has_regular)
|
|
|
|
|
{
|
2020-07-03 02:21:07 +00:00
|
|
|
|
gtk_strv_builder_init (&new_names);
|
2014-05-10 13:35:12 +00:00
|
|
|
|
for (i = 0; icon_names[i]; i++)
|
|
|
|
|
{
|
2019-05-21 12:26:19 +00:00
|
|
|
|
if (!icon_name_is_symbolic (icon_names[i], -1))
|
2020-07-03 02:21:07 +00:00
|
|
|
|
icon_name_list_add_icon (&new_names, dir_suffix, g_strconcat (icon_names[i], "-symbolic", NULL));
|
2014-05-10 13:35:12 +00:00
|
|
|
|
else
|
2020-07-03 02:21:07 +00:00
|
|
|
|
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
2014-05-11 00:30:50 +00:00
|
|
|
|
}
|
|
|
|
|
for (i = 0; icon_names[i]; i++)
|
|
|
|
|
{
|
2019-05-21 12:26:19 +00:00
|
|
|
|
if (!icon_name_is_symbolic (icon_names[i], -1))
|
2020-07-03 02:21:07 +00:00
|
|
|
|
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
2014-05-14 01:34:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon = real_choose_icon (self,
|
2020-07-03 02:21:07 +00:00
|
|
|
|
(const char **) gtk_strv_builder_get_data (&new_names),
|
2020-01-30 11:27:15 +00:00
|
|
|
|
size,
|
|
|
|
|
scale,
|
|
|
|
|
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
|
2020-03-05 06:56:01 +00:00
|
|
|
|
non_blocking);
|
2014-05-14 01:34:49 +00:00
|
|
|
|
|
2020-07-03 02:21:07 +00:00
|
|
|
|
gtk_strv_builder_clear (&new_names);
|
2014-05-14 01:34:49 +00:00
|
|
|
|
}
|
|
|
|
|
else if (dir_suffix)
|
|
|
|
|
{
|
2020-07-03 02:21:07 +00:00
|
|
|
|
gtk_strv_builder_init (&new_names);
|
2014-05-14 01:34:49 +00:00
|
|
|
|
for (i = 0; icon_names[i]; i++)
|
|
|
|
|
{
|
2020-07-03 02:21:07 +00:00
|
|
|
|
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
2014-05-10 13:35:12 +00:00
|
|
|
|
}
|
2014-05-11 00:30:50 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon = real_choose_icon (self,
|
2020-07-03 02:21:07 +00:00
|
|
|
|
(const char **) gtk_strv_builder_get_data (&new_names),
|
2020-01-30 11:27:15 +00:00
|
|
|
|
size,
|
|
|
|
|
scale,
|
|
|
|
|
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
|
2020-03-05 06:56:01 +00:00
|
|
|
|
non_blocking);
|
2014-05-11 00:30:50 +00:00
|
|
|
|
|
2020-07-03 02:21:07 +00:00
|
|
|
|
gtk_strv_builder_clear (&new_names);
|
2014-05-10 13:35:12 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon = real_choose_icon (self,
|
2020-01-30 11:27:15 +00:00
|
|
|
|
icon_names,
|
|
|
|
|
size,
|
|
|
|
|
scale,
|
|
|
|
|
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
|
2020-03-05 06:56:01 +00:00
|
|
|
|
non_blocking);
|
2014-05-10 13:35:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
return icon;
|
2014-05-10 13:35:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-07 16:25:18 +00:00
|
|
|
|
static void
|
|
|
|
|
load_icon_thread (GTask *task,
|
|
|
|
|
gpointer source_object,
|
|
|
|
|
gpointer task_data,
|
|
|
|
|
GCancellable *cancellable)
|
|
|
|
|
{
|
|
|
|
|
GtkIconPaintable *self = GTK_ICON_PAINTABLE (source_object);
|
|
|
|
|
|
|
|
|
|
g_mutex_lock (&self->texture_lock);
|
|
|
|
|
icon_ensure_texture__locked (self, TRUE);
|
|
|
|
|
g_mutex_unlock (&self->texture_lock);
|
|
|
|
|
g_task_return_pointer (task, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2007-05-18 20:19:12 +00:00
|
|
|
|
/**
|
2020-01-30 09:44:12 +00:00
|
|
|
|
* gtk_icon_theme_lookup_icon:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2013-05-10 16:06:00 +00:00
|
|
|
|
* @icon_name: the name of the icon to lookup
|
2020-02-05 16:08:29 +00:00
|
|
|
|
* @fallbacks: (nullable) (array zero-terminated=1):
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
* @size: desired icon size.
|
2020-01-30 09:44:12 +00:00
|
|
|
|
* @scale: the window scale this will be displayed on
|
2020-02-01 23:27:14 +00:00
|
|
|
|
* @direction: text direction the icon will be displayed in
|
2013-05-10 16:06:00 +00:00
|
|
|
|
* @flags: flags modifying the behavior of the icon lookup
|
|
|
|
|
*
|
2020-01-30 09:44:12 +00:00
|
|
|
|
* Looks up a named icon for a desired size and window scale, returning a
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* #GtkIconPaintable. The icon can then be rendered by using it as a #GdkPaintable,
|
2020-02-06 16:14:44 +00:00
|
|
|
|
* or you can get information such as the filename and size.
|
2020-01-30 09:44:12 +00:00
|
|
|
|
*
|
2020-02-04 02:53:22 +00:00
|
|
|
|
* If the available @icon_name is not available and @fallbacks are provided,
|
|
|
|
|
* they will be tried in order.
|
|
|
|
|
*
|
2020-02-05 16:08:29 +00:00
|
|
|
|
* If no matching icon is found, then a paintable that renders the
|
|
|
|
|
* "missing icon" icon is returned. If you need to do something else
|
|
|
|
|
* for missing icons you need to use gtk_icon_theme_has_icon().
|
|
|
|
|
*
|
2020-01-30 09:44:12 +00:00
|
|
|
|
* Note that you probably want to listen for icon theme changes and
|
2020-02-05 01:46:13 +00:00
|
|
|
|
* update the icon. This is usually done by overriding the
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* #GtkWidgetClass.css-changed() function.
|
2020-01-30 09:44:12 +00:00
|
|
|
|
*
|
2020-02-05 16:08:29 +00:00
|
|
|
|
* Returns: (transfer full): a #GtkIconPaintable object
|
|
|
|
|
* containing the icon.
|
2013-05-10 16:06:00 +00:00
|
|
|
|
*/
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *
|
2020-01-28 15:14:52 +00:00
|
|
|
|
gtk_icon_theme_lookup_icon (GtkIconTheme *self,
|
2020-02-04 02:53:22 +00:00
|
|
|
|
const char *icon_name,
|
|
|
|
|
const char *fallbacks[],
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size,
|
|
|
|
|
int scale,
|
2020-02-01 23:27:14 +00:00
|
|
|
|
GtkTextDirection direction,
|
2020-01-28 15:14:52 +00:00
|
|
|
|
GtkIconLookupFlags flags)
|
2007-05-18 20:19:12 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon;
|
2007-05-18 20:19:12 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
|
2007-05-18 20:19:12 +00:00
|
|
|
|
g_return_val_if_fail (icon_name != NULL, NULL);
|
2013-05-10 16:06:00 +00:00
|
|
|
|
g_return_val_if_fail (scale >= 1, NULL);
|
2007-05-18 20:19:12 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
GTK_DISPLAY_NOTE (self->display, ICONTHEME,
|
2018-01-14 14:53:48 +00:00
|
|
|
|
g_message ("looking up icon %s for scale %d", icon_name, scale));
|
2007-05-18 20:19:12 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
2020-02-04 03:26:19 +00:00
|
|
|
|
if (fallbacks)
|
2020-02-04 02:53:22 +00:00
|
|
|
|
{
|
|
|
|
|
gsize n_fallbacks = g_strv_length ((char **) fallbacks);
|
|
|
|
|
const char **names = g_new (const char *, n_fallbacks + 2);
|
|
|
|
|
|
|
|
|
|
names[0] = icon_name;
|
|
|
|
|
memcpy (&names[1], fallbacks, sizeof (char *) * n_fallbacks);
|
|
|
|
|
names[n_fallbacks + 1] = NULL;
|
|
|
|
|
|
2020-03-05 06:56:01 +00:00
|
|
|
|
icon = choose_icon (self, names, size, scale, direction, flags, FALSE);
|
2020-02-04 02:53:22 +00:00
|
|
|
|
|
|
|
|
|
g_free (names);
|
|
|
|
|
}
|
2013-10-16 01:19:17 +00:00
|
|
|
|
else
|
2007-05-18 20:19:12 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *names[2];
|
2013-10-16 01:19:17 +00:00
|
|
|
|
|
2007-05-18 20:19:12 +00:00
|
|
|
|
names[0] = icon_name;
|
|
|
|
|
names[1] = NULL;
|
|
|
|
|
|
2020-03-05 06:56:01 +00:00
|
|
|
|
icon = choose_icon (self, names, size, scale, direction, flags, FALSE);
|
2007-05-18 20:19:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gtk_icon_theme_unlock (self);
|
|
|
|
|
|
2020-02-10 10:43:47 +00:00
|
|
|
|
if (flags & GTK_ICON_LOOKUP_PRELOAD)
|
2020-02-07 16:25:18 +00:00
|
|
|
|
{
|
|
|
|
|
gboolean has_texture = FALSE;
|
|
|
|
|
|
|
|
|
|
/* If we fail to get the lock it is because some other thread is
|
|
|
|
|
currently loading the icon, so we need to do nothing */
|
|
|
|
|
if (g_mutex_trylock (&icon->texture_lock))
|
|
|
|
|
{
|
|
|
|
|
has_texture = icon->texture != NULL;
|
|
|
|
|
g_mutex_unlock (&icon->texture_lock);
|
|
|
|
|
|
|
|
|
|
if (!has_texture)
|
|
|
|
|
{
|
|
|
|
|
GTask *task = g_task_new (icon, NULL, NULL, NULL);
|
|
|
|
|
g_task_run_in_thread (task, load_icon_thread);
|
|
|
|
|
g_object_unref (task);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
return icon;
|
2007-05-18 20:19:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
/* Error quark */
|
|
|
|
|
GQuark
|
|
|
|
|
gtk_icon_theme_error_quark (void)
|
|
|
|
|
{
|
2006-04-04 03:25:16 +00:00
|
|
|
|
return g_quark_from_static_string ("gtk-icon-theme-error-quark");
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-28 13:54:18 +00:00
|
|
|
|
void
|
|
|
|
|
gtk_icon_theme_lookup_symbolic_colors (GtkCssStyle *style,
|
|
|
|
|
GdkRGBA *color_out,
|
|
|
|
|
GdkRGBA *success_out,
|
|
|
|
|
GdkRGBA *warning_out,
|
|
|
|
|
GdkRGBA *error_out)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-01-28 13:54:18 +00:00
|
|
|
|
GtkCssValue *palette, *color;
|
|
|
|
|
const GdkRGBA *lookup;
|
2019-08-30 18:54:16 +00:00
|
|
|
|
|
2020-01-28 13:54:18 +00:00
|
|
|
|
color = style->core->color;
|
|
|
|
|
palette = style->core->icon_palette;
|
|
|
|
|
*color_out = *gtk_css_color_value_get_rgba (color);
|
2013-05-10 16:06:00 +00:00
|
|
|
|
|
2020-01-28 13:54:18 +00:00
|
|
|
|
lookup = gtk_css_palette_value_get_color (palette, "success");
|
|
|
|
|
if (lookup)
|
|
|
|
|
*success_out = *lookup;
|
|
|
|
|
else
|
|
|
|
|
*success_out = *color_out;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-28 13:54:18 +00:00
|
|
|
|
lookup = gtk_css_palette_value_get_color (palette, "warning");
|
|
|
|
|
if (lookup)
|
|
|
|
|
*warning_out = *lookup;
|
|
|
|
|
else
|
|
|
|
|
*warning_out = *color_out;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-28 13:54:18 +00:00
|
|
|
|
lookup = gtk_css_palette_value_get_color (palette, "error");
|
|
|
|
|
if (lookup)
|
|
|
|
|
*error_out = *lookup;
|
|
|
|
|
else
|
|
|
|
|
*error_out = *color_out;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-28 13:54:18 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_theme_has_icon:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* @icon_name: the name of an icon
|
2020-01-24 15:22:26 +00:00
|
|
|
|
*
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* Checks whether an icon theme includes an icon
|
|
|
|
|
* for a particular name.
|
2020-01-24 15:22:26 +00:00
|
|
|
|
*
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* Returns: %TRUE if @self includes an
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* icon for @icon_name.
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*/
|
2020-01-30 08:12:36 +00:00
|
|
|
|
gboolean
|
2019-09-08 12:57:40 +00:00
|
|
|
|
gtk_icon_theme_has_icon (GtkIconTheme *self,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *icon_name)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2004-10-21 18:44:08 +00:00
|
|
|
|
GList *l;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gboolean res = FALSE;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_ICON_THEME (self), FALSE);
|
2009-01-22 15:15:40 +00:00
|
|
|
|
g_return_val_if_fail (icon_name != NULL, FALSE);
|
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
2020-01-28 12:47:59 +00:00
|
|
|
|
ensure_valid_themes (self, FALSE);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
for (l = self->themes; l; l = l->next)
|
2014-06-20 01:37:01 +00:00
|
|
|
|
{
|
|
|
|
|
if (theme_has_icon (l->data, icon_name))
|
2020-01-24 15:22:26 +00:00
|
|
|
|
{
|
|
|
|
|
res = TRUE;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2014-06-20 01:37:01 +00:00
|
|
|
|
}
|
2003-12-07 22:53:22 +00:00
|
|
|
|
|
2020-01-24 15:22:26 +00:00
|
|
|
|
out:
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
|
|
|
|
|
|
|
|
|
return res;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-07-17 03:55:07 +00:00
|
|
|
|
static void
|
2014-06-19 23:42:53 +00:00
|
|
|
|
add_size (gpointer key,
|
|
|
|
|
gpointer value,
|
|
|
|
|
gpointer user_data)
|
2004-07-17 03:55:07 +00:00
|
|
|
|
{
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int **res_p = user_data;
|
2004-07-17 03:55:07 +00:00
|
|
|
|
|
|
|
|
|
**res_p = GPOINTER_TO_INT (key);
|
|
|
|
|
|
2004-08-03 18:51:26 +00:00
|
|
|
|
(*res_p)++;
|
2004-07-17 03:55:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_theme_get_icon_sizes:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2004-07-17 03:55:07 +00:00
|
|
|
|
* @icon_name: the name of an icon
|
2020-01-30 08:12:36 +00:00
|
|
|
|
*
|
2004-07-17 03:55:07 +00:00
|
|
|
|
* Returns an array of integers describing the sizes at which
|
2020-01-30 08:12:36 +00:00
|
|
|
|
* the icon is available without scaling. A size of -1 means
|
|
|
|
|
* that the icon is available in a scalable format. The array
|
2004-07-17 03:55:07 +00:00
|
|
|
|
* is zero-terminated.
|
2020-01-24 15:22:26 +00:00
|
|
|
|
*
|
2019-08-25 12:52:24 +00:00
|
|
|
|
* Returns: (array zero-terminated=1) (transfer full): A newly
|
2014-05-26 16:42:23 +00:00
|
|
|
|
* allocated array describing the sizes at which the icon is
|
|
|
|
|
* available. The array should be freed with g_free() when it is no
|
|
|
|
|
* longer needed.
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*/
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int *
|
2019-09-08 12:57:40 +00:00
|
|
|
|
gtk_icon_theme_get_icon_sizes (GtkIconTheme *self,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *icon_name)
|
2004-07-17 03:55:07 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
GList *l;
|
|
|
|
|
int i;
|
2004-07-17 03:55:07 +00:00
|
|
|
|
GHashTable *sizes;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int *result, *r;
|
2004-07-17 03:55:07 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
2020-01-28 12:47:59 +00:00
|
|
|
|
ensure_valid_themes (self, FALSE);
|
2004-07-17 03:55:07 +00:00
|
|
|
|
|
|
|
|
|
sizes = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
for (l = self->themes; l; l = l->next)
|
2004-07-17 03:55:07 +00:00
|
|
|
|
{
|
|
|
|
|
IconTheme *theme = l->data;
|
2020-02-07 10:54:00 +00:00
|
|
|
|
const char *interned_icon_name = gtk_string_set_lookup (&theme->icons, icon_name);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < theme->dir_sizes->len; i++)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
IconThemeDirSize *dir_size = &g_array_index (theme->dir_sizes, IconThemeDirSize, i);
|
2004-10-19 18:45:41 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (dir_size->type != ICON_THEME_DIR_SCALABLE && g_hash_table_lookup_extended (sizes, GINT_TO_POINTER (dir_size->size), NULL, NULL))
|
2007-12-03 17:44:27 +00:00
|
|
|
|
continue;
|
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
if (!g_hash_table_contains (dir_size->icon_hash, interned_icon_name))
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (dir_size->type == ICON_THEME_DIR_SCALABLE)
|
|
|
|
|
g_hash_table_insert (sizes, GINT_TO_POINTER (-1), NULL);
|
|
|
|
|
else
|
|
|
|
|
g_hash_table_insert (sizes, GINT_TO_POINTER (dir_size->size), NULL);
|
2014-06-19 23:42:53 +00:00
|
|
|
|
}
|
2004-07-17 03:55:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-24 13:54:49 +00:00
|
|
|
|
r = result = g_new0 (int, g_hash_table_size (sizes) + 1);
|
2004-07-17 03:55:07 +00:00
|
|
|
|
|
2004-08-16 18:38:55 +00:00
|
|
|
|
g_hash_table_foreach (sizes, add_size, &r);
|
2004-07-17 03:55:07 +00:00
|
|
|
|
g_hash_table_destroy (sizes);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
|
|
|
|
|
2004-07-17 03:55:07 +00:00
|
|
|
|
return result;
|
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
static void
|
2014-06-19 23:42:53 +00:00
|
|
|
|
add_key_to_hash (gpointer key,
|
|
|
|
|
gpointer value,
|
|
|
|
|
gpointer user_data)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
GHashTable *hash = user_data;
|
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
g_hash_table_insert (hash, key, key);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* gtk_icon_theme_get_icon_names:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2014-04-11 16:52:39 +00:00
|
|
|
|
*
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* Lists the names of icons in the current icon theme.
|
2009-12-10 10:23:40 +00:00
|
|
|
|
*
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* Returns: (element-type utf8) (transfer full): a string array
|
2014-06-19 23:42:53 +00:00
|
|
|
|
* holding the names of all the icons in the theme. You must
|
2020-02-18 05:56:37 +00:00
|
|
|
|
* free the array using g_strfreev().
|
2014-06-19 23:42:53 +00:00
|
|
|
|
*/
|
2020-02-18 05:56:37 +00:00
|
|
|
|
char **
|
|
|
|
|
gtk_icon_theme_get_icon_names (GtkIconTheme *self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
GHashTable *icons;
|
2020-02-18 05:56:37 +00:00
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
char **names;
|
|
|
|
|
char *key;
|
|
|
|
|
int i;
|
|
|
|
|
GList *l;
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_lock (self);
|
|
|
|
|
|
2020-01-28 12:47:59 +00:00
|
|
|
|
ensure_valid_themes (self, FALSE);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
icons = g_hash_table_new (g_str_hash, g_str_equal);
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
l = self->themes;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
while (l != NULL)
|
|
|
|
|
{
|
2020-02-07 10:54:00 +00:00
|
|
|
|
IconTheme *theme = l->data;
|
|
|
|
|
gtk_string_set_list (&theme->icons, icons);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
l = l->next;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-02 00:19:50 +00:00
|
|
|
|
g_hash_table_foreach (self->unthemed_icons,
|
|
|
|
|
add_key_to_hash,
|
|
|
|
|
icons);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
names = g_new (char *, g_hash_table_size (icons) + 1);
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
g_hash_table_iter_init (&iter, icons);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
|
|
|
|
|
names[i++] = g_strdup (key);
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
names[i] = NULL;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
g_hash_table_destroy (icons);
|
2020-01-24 15:22:26 +00:00
|
|
|
|
|
|
|
|
|
gtk_icon_theme_unlock (self);
|
|
|
|
|
|
2020-02-18 05:56:37 +00:00
|
|
|
|
return names;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-03-15 18:40:16 +00:00
|
|
|
|
static gboolean
|
2019-09-08 12:57:40 +00:00
|
|
|
|
rescan_themes (GtkIconTheme *self)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int stat_res;
|
2011-10-03 15:25:33 +00:00
|
|
|
|
GStatBuf stat_buf;
|
2020-04-25 18:18:29 +00:00
|
|
|
|
guint i;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-04-25 18:18:29 +00:00
|
|
|
|
for (i = 0; i < self->dir_mtimes->len; i++)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-04-25 18:18:29 +00:00
|
|
|
|
const IconThemeDirMtime *dir_mtime = &g_array_index (self->dir_mtimes, IconThemeDirMtime, i);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2004-12-12 21:09:13 +00:00
|
|
|
|
stat_res = g_stat (dir_mtime->dir, &stat_buf);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
/* dir mtime didn't change */
|
2015-02-23 20:49:08 +00:00
|
|
|
|
if (stat_res == 0 && dir_mtime->exists &&
|
2014-06-19 23:42:53 +00:00
|
|
|
|
S_ISDIR (stat_buf.st_mode) &&
|
|
|
|
|
dir_mtime->mtime == stat_buf.st_mtime)
|
|
|
|
|
continue;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
/* didn't exist before, and still doesn't */
|
2015-02-23 20:49:08 +00:00
|
|
|
|
if (!dir_mtime->exists &&
|
2014-06-19 23:42:53 +00:00
|
|
|
|
(stat_res != 0 || !S_ISDIR (stat_buf.st_mode)))
|
|
|
|
|
continue;
|
2007-03-15 18:40:16 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
2007-03-15 18:40:16 +00:00
|
|
|
|
|
2020-07-31 15:22:16 +00:00
|
|
|
|
self->last_stat_time = g_get_monotonic_time ();
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
static IconTheme *
|
|
|
|
|
theme_new (const char *theme_name,
|
|
|
|
|
GKeyFile *theme_file)
|
|
|
|
|
{
|
|
|
|
|
IconTheme *theme;
|
|
|
|
|
|
|
|
|
|
theme = g_new0 (IconTheme, 1);
|
|
|
|
|
theme->name = g_strdup (theme_name);
|
|
|
|
|
theme->dir_sizes = g_array_new (FALSE, FALSE, sizeof (IconThemeDirSize));
|
|
|
|
|
theme->dirs = g_array_new (FALSE, FALSE, sizeof (IconThemeDir));
|
2020-02-07 10:54:00 +00:00
|
|
|
|
gtk_string_set_init (&theme->icons);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
|
|
|
|
theme->display_name =
|
|
|
|
|
g_key_file_get_locale_string (theme_file, "Icon Theme", "Name", NULL, NULL);
|
|
|
|
|
if (!theme->display_name)
|
|
|
|
|
g_warning ("Theme file for %s has no name", theme_name);
|
|
|
|
|
|
|
|
|
|
theme->comment =
|
|
|
|
|
g_key_file_get_locale_string (theme_file,
|
|
|
|
|
"Icon Theme", "Comment",
|
|
|
|
|
NULL, NULL);
|
|
|
|
|
return theme;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
static void
|
|
|
|
|
theme_destroy (IconTheme *theme)
|
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
gsize i;
|
|
|
|
|
|
|
|
|
|
g_free (theme->name);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
g_free (theme->display_name);
|
|
|
|
|
g_free (theme->comment);
|
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
for (i = 0; i < theme->dir_sizes->len; i++)
|
|
|
|
|
theme_dir_size_destroy (&g_array_index (theme->dir_sizes, IconThemeDirSize, i));
|
|
|
|
|
g_array_free (theme->dir_sizes, TRUE);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < theme->dirs->len; i++)
|
|
|
|
|
theme_dir_destroy (&g_array_index (theme->dirs, IconThemeDir, i));
|
|
|
|
|
g_array_free (theme->dirs, TRUE);
|
2020-02-07 10:54:00 +00:00
|
|
|
|
|
|
|
|
|
gtk_string_set_destroy (&theme->icons);
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
g_free (theme);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
theme_dir_size_destroy (IconThemeDirSize *dir)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (dir->icon_hash)
|
|
|
|
|
g_hash_table_destroy (dir->icon_hash);
|
|
|
|
|
if (dir->icon_files)
|
|
|
|
|
g_array_free (dir->icon_files, TRUE);
|
|
|
|
|
}
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
static void
|
|
|
|
|
theme_dir_destroy (IconThemeDir *dir)
|
|
|
|
|
{
|
|
|
|
|
g_free (dir->path);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
theme_dir_size_difference (IconThemeDirSize *dir_size,
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size,
|
|
|
|
|
int scale)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int scaled_size, scaled_dir_size;
|
|
|
|
|
int min, max;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
|
|
|
|
|
scaled_size = size * scale;
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
scaled_dir_size = dir_size->size * dir_size->scale;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
switch (dir_size->type)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
case ICON_THEME_DIR_FIXED:
|
2013-05-10 16:06:00 +00:00
|
|
|
|
return abs (scaled_size - scaled_dir_size);
|
2017-10-06 19:19:42 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
case ICON_THEME_DIR_SCALABLE:
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (scaled_size < (dir_size->min_size * dir_size->scale))
|
|
|
|
|
return (dir_size->min_size * dir_size->scale) - scaled_size;
|
|
|
|
|
if (size > (dir_size->max_size * dir_size->scale))
|
|
|
|
|
return scaled_size - (dir_size->max_size * dir_size->scale);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
return 0;
|
2017-10-06 19:19:42 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
case ICON_THEME_DIR_THRESHOLD:
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
min = (dir_size->size - dir_size->threshold) * dir_size->scale;
|
|
|
|
|
max = (dir_size->size + dir_size->threshold) * dir_size->scale;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
if (scaled_size < min)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
return min - scaled_size;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
if (scaled_size > max)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
return scaled_size - max;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
return 0;
|
2017-10-06 19:19:42 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
case ICON_THEME_DIR_UNTHEMED:
|
2017-10-06 19:19:42 +00:00
|
|
|
|
default:
|
2003-07-02 22:44:09 +00:00
|
|
|
|
g_assert_not_reached ();
|
2017-10-06 19:19:42 +00:00
|
|
|
|
return 1000;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-24 18:40:36 +00:00
|
|
|
|
static const char *
|
2020-02-04 08:35:20 +00:00
|
|
|
|
string_from_suffix (IconCacheFlag suffix)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
switch (suffix)
|
|
|
|
|
{
|
2020-02-04 08:35:20 +00:00
|
|
|
|
case ICON_CACHE_FLAG_XPM_SUFFIX:
|
2003-07-02 22:44:09 +00:00
|
|
|
|
return ".xpm";
|
2020-02-04 08:35:20 +00:00
|
|
|
|
case ICON_CACHE_FLAG_SVG_SUFFIX:
|
2003-07-02 22:44:09 +00:00
|
|
|
|
return ".svg";
|
2020-02-04 08:35:20 +00:00
|
|
|
|
case ICON_CACHE_FLAG_PNG_SUFFIX:
|
2003-07-02 22:44:09 +00:00
|
|
|
|
return ".png";
|
2020-02-04 08:35:20 +00:00
|
|
|
|
case ICON_CACHE_FLAG_SYMBOLIC_PNG_SUFFIX:
|
2014-07-30 16:05:48 +00:00
|
|
|
|
return ".symbolic.png";
|
2020-02-04 08:35:20 +00:00
|
|
|
|
case ICON_CACHE_FLAG_NONE:
|
|
|
|
|
case ICON_CACHE_FLAG_HAS_ICON_FILE:
|
2003-07-02 22:44:09 +00:00
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached();
|
2017-10-06 19:19:42 +00:00
|
|
|
|
return NULL;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 08:35:20 +00:00
|
|
|
|
static inline IconCacheFlag
|
2020-07-24 18:40:36 +00:00
|
|
|
|
suffix_from_name (const char *name)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2019-09-01 08:20:00 +00:00
|
|
|
|
const gsize name_len = strlen (name);
|
2014-09-05 17:15:14 +00:00
|
|
|
|
|
2019-09-01 08:20:00 +00:00
|
|
|
|
if (name_len > 4)
|
2014-09-05 17:15:14 +00:00
|
|
|
|
{
|
2019-09-01 08:20:00 +00:00
|
|
|
|
if (name_len > strlen (".symbolic.png"))
|
|
|
|
|
{
|
|
|
|
|
if (strcmp (name + name_len - strlen (".symbolic.png"), ".symbolic.png") == 0)
|
2020-02-04 08:35:20 +00:00
|
|
|
|
return ICON_CACHE_FLAG_SYMBOLIC_PNG_SUFFIX;
|
2019-09-01 08:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strcmp (name + name_len - strlen (".png"), ".png") == 0)
|
2020-02-04 08:35:20 +00:00
|
|
|
|
return ICON_CACHE_FLAG_PNG_SUFFIX;
|
2019-09-01 08:20:00 +00:00
|
|
|
|
|
|
|
|
|
if (strcmp (name + name_len - strlen (".svg"), ".svg") == 0)
|
2020-02-04 08:35:20 +00:00
|
|
|
|
return ICON_CACHE_FLAG_SVG_SUFFIX;
|
2019-09-01 08:20:00 +00:00
|
|
|
|
|
|
|
|
|
if (strcmp (name + name_len - strlen (".xpm"), ".xpm") == 0)
|
2020-02-04 08:35:20 +00:00
|
|
|
|
return ICON_CACHE_FLAG_XPM_SUFFIX;
|
2014-09-05 17:15:14 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-04 08:35:20 +00:00
|
|
|
|
return ICON_CACHE_FLAG_NONE;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 08:35:20 +00:00
|
|
|
|
static IconCacheFlag
|
|
|
|
|
best_suffix (IconCacheFlag suffix,
|
|
|
|
|
gboolean allow_svg)
|
|
|
|
|
{
|
|
|
|
|
if ((suffix & ICON_CACHE_FLAG_SYMBOLIC_PNG_SUFFIX) != 0)
|
|
|
|
|
return ICON_CACHE_FLAG_SYMBOLIC_PNG_SUFFIX;
|
|
|
|
|
else if ((suffix & ICON_CACHE_FLAG_PNG_SUFFIX) != 0)
|
|
|
|
|
return ICON_CACHE_FLAG_PNG_SUFFIX;
|
|
|
|
|
else if (allow_svg && ((suffix & ICON_CACHE_FLAG_SVG_SUFFIX) != 0))
|
|
|
|
|
return ICON_CACHE_FLAG_SVG_SUFFIX;
|
|
|
|
|
else if ((suffix & ICON_CACHE_FLAG_XPM_SUFFIX) != 0)
|
|
|
|
|
return ICON_CACHE_FLAG_XPM_SUFFIX;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
else
|
2020-02-04 08:35:20 +00:00
|
|
|
|
return ICON_CACHE_FLAG_NONE;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2013-05-10 16:06:00 +00:00
|
|
|
|
/* returns TRUE if dir_a is a better match */
|
|
|
|
|
static gboolean
|
2020-07-24 13:54:49 +00:00
|
|
|
|
compare_dir_size_matches (IconThemeDirSize *dir_a, int difference_a,
|
|
|
|
|
IconThemeDirSize *dir_b, int difference_b,
|
|
|
|
|
int requested_size,
|
|
|
|
|
int requested_scale)
|
2013-05-10 16:06:00 +00:00
|
|
|
|
{
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int diff_a;
|
|
|
|
|
int diff_b;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
|
|
|
|
|
if (difference_a == 0)
|
|
|
|
|
{
|
|
|
|
|
if (difference_b != 0)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
return TRUE;
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2013-05-10 16:06:00 +00:00
|
|
|
|
/* a and b both exact matches */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If scaling, *always* prefer downscaling */
|
|
|
|
|
if (dir_a->size >= requested_size &&
|
2014-06-19 23:42:53 +00:00
|
|
|
|
dir_b->size < requested_size)
|
|
|
|
|
return TRUE;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
|
|
|
|
|
if (dir_a->size < requested_size &&
|
2014-06-19 23:42:53 +00:00
|
|
|
|
dir_b->size >= requested_size)
|
|
|
|
|
return FALSE;
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2013-05-10 16:06:00 +00:00
|
|
|
|
/* Otherwise prefer the closest match */
|
|
|
|
|
|
|
|
|
|
if (difference_a < difference_b)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
return TRUE;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
|
|
|
|
|
if (difference_a > difference_b)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
return FALSE;
|
2013-05-10 16:06:00 +00:00
|
|
|
|
|
|
|
|
|
/* same pixel difference */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dir_a->scale == requested_scale &&
|
|
|
|
|
dir_b->scale != requested_scale)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
if (dir_a->scale != requested_scale &&
|
|
|
|
|
dir_b->scale == requested_scale)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* a and b both match the scale */
|
|
|
|
|
|
|
|
|
|
if (dir_a->type != ICON_THEME_DIR_SCALABLE &&
|
|
|
|
|
dir_b->type == ICON_THEME_DIR_SCALABLE)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
if (dir_a->type == ICON_THEME_DIR_SCALABLE &&
|
|
|
|
|
dir_b->type != ICON_THEME_DIR_SCALABLE)
|
|
|
|
|
return FALSE;
|
2020-01-30 08:12:36 +00:00
|
|
|
|
|
2013-05-10 16:06:00 +00:00
|
|
|
|
/* a and b both are scalable */
|
|
|
|
|
|
|
|
|
|
diff_a = abs (requested_size * requested_scale - dir_a->size * dir_a->scale);
|
|
|
|
|
diff_b = abs (requested_size * requested_scale - dir_b->size * dir_b->scale);
|
|
|
|
|
|
|
|
|
|
return diff_a <= diff_b;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
static GtkIconPaintable *
|
2014-06-19 23:42:53 +00:00
|
|
|
|
theme_lookup_icon (IconTheme *theme,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *icon_name, /* interned */
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size,
|
|
|
|
|
int scale,
|
2019-05-21 12:53:03 +00:00
|
|
|
|
gboolean allow_svg)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
IconThemeDirSize *min_dir_size;
|
|
|
|
|
IconThemeFile *min_file;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int min_difference;
|
2020-02-04 08:35:20 +00:00
|
|
|
|
IconCacheFlag min_suffix;
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
int i;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
/* Its not uncommon with misses, so we do an early check which allows us do
|
2020-02-07 10:54:00 +00:00
|
|
|
|
* do a lot less work.
|
|
|
|
|
* We also intern the name so later hash lookups are faster. */
|
|
|
|
|
icon_name = gtk_string_set_lookup (&theme->icons, icon_name);
|
|
|
|
|
if (icon_name == NULL)
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
return FALSE;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
min_difference = G_MAXINT;
|
|
|
|
|
min_dir_size = NULL;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
for (i = 0; i < theme->dir_sizes->len; i++)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
IconThemeDirSize *dir_size = &g_array_index (theme->dir_sizes, IconThemeDirSize, i);
|
|
|
|
|
IconThemeFile *file;
|
|
|
|
|
guint best_suffix;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int difference;
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
gpointer file_index;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (!g_hash_table_lookup_extended (dir_size->icon_hash, icon_name, NULL, &file_index))
|
|
|
|
|
continue;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
file = &g_array_index (dir_size->icon_files, IconThemeFile, GPOINTER_TO_INT(file_index));
|
2013-09-23 10:37:36 +00:00
|
|
|
|
|
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (allow_svg)
|
|
|
|
|
best_suffix = file->best_suffix;
|
|
|
|
|
else
|
|
|
|
|
best_suffix = file->best_suffix_no_svg;
|
2013-09-23 10:37:36 +00:00
|
|
|
|
|
2020-02-04 08:35:20 +00:00
|
|
|
|
if (best_suffix == ICON_CACHE_FLAG_NONE)
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
continue;
|
2014-07-15 16:42:39 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
difference = theme_dir_size_difference (dir_size, size, scale);
|
|
|
|
|
if (min_dir_size == NULL ||
|
|
|
|
|
compare_dir_size_matches (dir_size, difference,
|
|
|
|
|
min_dir_size, min_difference,
|
|
|
|
|
size, scale))
|
2007-04-25 18:01:44 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
min_dir_size = dir_size;
|
|
|
|
|
min_file = file;
|
|
|
|
|
min_suffix = best_suffix;
|
|
|
|
|
min_difference = difference;
|
2007-04-25 18:01:44 +00:00
|
|
|
|
}
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
}
|
2013-06-19 07:32:38 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (min_dir_size)
|
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon;
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
IconThemeDir *dir = &g_array_index (theme->dirs, IconThemeDir, min_file->dir_index);
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *filename;
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
2020-02-10 10:40:00 +00:00
|
|
|
|
icon = icon_paintable_new (icon_name, size, scale);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
|
|
|
|
filename = g_strconcat (icon_name, string_from_suffix (min_suffix), NULL);
|
|
|
|
|
icon->filename = g_build_filename (dir->path, filename, NULL);
|
2020-02-04 08:35:20 +00:00
|
|
|
|
icon->is_svg = min_suffix == ICON_CACHE_FLAG_SVG_SUFFIX;
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
icon->is_resource = dir->is_resource;
|
2020-02-05 16:08:29 +00:00
|
|
|
|
icon->is_symbolic = icon_uri_is_symbolic (filename, -1);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
g_free (filename);
|
Update spec.
2005-03-15 Anders Carlsson <andersca@imendio.com>
* docs/iconcache.txt:
Update spec.
* gtk/gtkiconcache.c: (find_image_offset),
(_gtk_icon_cache_get_icon_flags), (_gtk_icon_cache_add_icons),
(_gtk_icon_cache_get_icon), (_gtk_icon_cache_get_icon_data):
* gtk/gtkiconcache.h:
Update to be able to fetch pixbuf data and icon metadata.
* gtk/gtkicontheme.c: (theme_lookup_icon), (gtk_icon_info_free),
(icon_info_ensure_scale_and_pixbuf):
Use new cache functions.
* gtk/updateiconcache.c: (foreach_remove_func), (load_icon_data),
(maybe_cache_image_data), (scan_directory), (write_pixdata),
(get_image_meta_data_size), (get_image_pixel_data_size),
(get_image_data_size), (get_single_node_size), (get_bucket_size),
(write_bucket), (main):
Update to write pixbuf data as well as information from .icon
files.
2005-03-15 13:18:25 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
return icon;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2007-01-15 02:56:33 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-20 01:37:01 +00:00
|
|
|
|
static gboolean
|
|
|
|
|
theme_has_icon (IconTheme *theme,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *icon_name)
|
2014-06-20 01:37:01 +00:00
|
|
|
|
{
|
2020-02-07 10:54:00 +00:00
|
|
|
|
return gtk_string_set_lookup (&theme->icons, icon_name) != NULL;
|
2014-06-20 01:37:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-01 08:04:32 +00:00
|
|
|
|
static GHashTable *
|
2019-09-08 12:57:40 +00:00
|
|
|
|
scan_directory (GtkIconTheme *self,
|
2020-02-07 10:54:00 +00:00
|
|
|
|
char *full_dir,
|
|
|
|
|
GtkStringSet *set)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
GDir *gdir;
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *name;
|
2019-09-01 08:04:32 +00:00
|
|
|
|
GHashTable *icons = NULL;
|
2004-10-19 18:45:41 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
GTK_DISPLAY_NOTE (self->display, ICONTHEME,
|
2018-01-14 14:53:48 +00:00
|
|
|
|
g_message ("scanning directory %s", full_dir));
|
2014-06-20 16:11:55 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
gdir = g_dir_open (full_dir, 0, NULL);
|
|
|
|
|
|
|
|
|
|
if (gdir == NULL)
|
2019-09-01 08:04:32 +00:00
|
|
|
|
return NULL;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
while ((name = g_dir_read_name (gdir)))
|
|
|
|
|
{
|
2020-02-07 10:54:00 +00:00
|
|
|
|
const char *interned;
|
2020-02-04 08:35:20 +00:00
|
|
|
|
IconCacheFlag suffix, hash_suffix;
|
2006-04-18 13:58:30 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
suffix = suffix_from_name (name);
|
2020-02-04 08:35:20 +00:00
|
|
|
|
if (suffix == ICON_CACHE_FLAG_NONE)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
continue;
|
2006-04-18 13:58:30 +00:00
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
strip_suffix_inline ((char *)name);
|
|
|
|
|
interned = gtk_string_set_add (set, name);
|
2019-09-01 08:04:32 +00:00
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
if (!icons)
|
|
|
|
|
icons = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
|
2006-04-18 13:58:30 +00:00
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
hash_suffix = GPOINTER_TO_INT (g_hash_table_lookup (icons, interned));
|
2011-05-05 14:13:13 +00:00
|
|
|
|
/* takes ownership of base_name */
|
2020-02-07 10:54:00 +00:00
|
|
|
|
g_hash_table_replace (icons, (char *)interned, GUINT_TO_POINTER (hash_suffix|suffix));
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2019-09-01 08:04:32 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
g_dir_close (gdir);
|
2014-06-20 16:11:55 +00:00
|
|
|
|
|
2019-09-01 08:04:32 +00:00
|
|
|
|
return icons;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
static GHashTable *
|
|
|
|
|
scan_resource_directory (GtkIconTheme *self,
|
2020-02-07 10:54:00 +00:00
|
|
|
|
char *full_dir,
|
|
|
|
|
GtkStringSet *set)
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
{
|
|
|
|
|
GHashTable *icons = NULL;
|
|
|
|
|
char **children;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
GTK_DISPLAY_NOTE (self->display, ICONTHEME,
|
|
|
|
|
g_message ("scanning resource directory %s", full_dir));
|
|
|
|
|
|
|
|
|
|
children = g_resources_enumerate_children (full_dir, 0, NULL);
|
|
|
|
|
|
2020-02-04 23:25:15 +00:00
|
|
|
|
if (children)
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
{
|
2020-02-04 23:25:15 +00:00
|
|
|
|
for (i = 0; children[i]; i++)
|
|
|
|
|
{
|
2020-02-07 10:54:00 +00:00
|
|
|
|
char *name = children[i];
|
|
|
|
|
const char *interned;
|
2020-02-04 23:25:15 +00:00
|
|
|
|
IconCacheFlag suffix, hash_suffix;
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
2020-02-04 23:25:15 +00:00
|
|
|
|
suffix = suffix_from_name (name);
|
|
|
|
|
if (suffix == ICON_CACHE_FLAG_NONE)
|
|
|
|
|
continue;
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
2020-02-04 23:25:15 +00:00
|
|
|
|
if (!icons)
|
2020-02-07 10:54:00 +00:00
|
|
|
|
icons = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
strip_suffix_inline (name);
|
|
|
|
|
interned = gtk_string_set_add (set, name);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
hash_suffix = GPOINTER_TO_INT (g_hash_table_lookup (icons, interned));
|
2020-02-04 23:25:15 +00:00
|
|
|
|
/* takes ownership of base_name */
|
2020-02-07 10:54:00 +00:00
|
|
|
|
g_hash_table_replace (icons, (char *)interned, GUINT_TO_POINTER (hash_suffix|suffix));
|
2020-02-04 23:25:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_strfreev (children);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return icons;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
theme_dir_size_equal (IconThemeDirSize *a,
|
|
|
|
|
IconThemeDirSize *b)
|
|
|
|
|
{
|
|
|
|
|
return
|
|
|
|
|
a->type == b->type &&
|
|
|
|
|
a->size == b->size &&
|
|
|
|
|
a->min_size == b->min_size &&
|
|
|
|
|
a->max_size == b->max_size &&
|
|
|
|
|
a->threshold == b->threshold &&
|
|
|
|
|
a->scale == b->scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint32
|
|
|
|
|
theme_ensure_dir_size (IconTheme *theme,
|
|
|
|
|
IconThemeDirType type,
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size,
|
|
|
|
|
int min_size,
|
|
|
|
|
int max_size,
|
|
|
|
|
int threshold,
|
|
|
|
|
int scale)
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
{
|
|
|
|
|
guint32 index;
|
|
|
|
|
IconThemeDirSize new = { 0 };
|
|
|
|
|
|
|
|
|
|
new.type = type;
|
|
|
|
|
new.size = size;
|
|
|
|
|
new.min_size = min_size;
|
|
|
|
|
new.max_size = max_size;
|
|
|
|
|
new.threshold = threshold;
|
|
|
|
|
new.scale = scale;
|
|
|
|
|
|
|
|
|
|
for (index = 0; index < theme->dir_sizes->len; index++)
|
|
|
|
|
{
|
|
|
|
|
IconThemeDirSize *dir_size = &g_array_index (theme->dir_sizes, IconThemeDirSize, index);
|
|
|
|
|
|
|
|
|
|
if (theme_dir_size_equal (dir_size, &new))
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
new.icon_files = g_array_new (FALSE, FALSE, sizeof (IconThemeFile));
|
2020-02-07 10:54:00 +00:00
|
|
|
|
/* The keys are interned strings, so use direct hash/equal */
|
|
|
|
|
new.icon_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
|
|
|
|
index = theme->dir_sizes->len;
|
|
|
|
|
g_array_append_val (theme->dir_sizes, new);
|
|
|
|
|
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint32
|
|
|
|
|
theme_add_icon_dir (IconTheme *theme,
|
|
|
|
|
gboolean is_resource,
|
|
|
|
|
char *path /* takes ownership */)
|
|
|
|
|
{
|
|
|
|
|
IconThemeDir new_dir = { 0 };
|
|
|
|
|
guint32 dir_index;
|
|
|
|
|
|
|
|
|
|
new_dir.is_resource = is_resource;
|
|
|
|
|
new_dir.path = path;
|
|
|
|
|
|
|
|
|
|
dir_index = theme->dirs->len;
|
|
|
|
|
g_array_append_val (theme->dirs, new_dir);
|
|
|
|
|
return dir_index;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
theme_add_icon_file (IconTheme *theme,
|
2020-02-07 10:54:00 +00:00
|
|
|
|
const char *icon_name, /* interned */
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
guint suffixes,
|
|
|
|
|
IconThemeDirSize *dir_size,
|
|
|
|
|
guint dir_index)
|
|
|
|
|
{
|
|
|
|
|
IconThemeFile new_file = { 0 };
|
|
|
|
|
guint index;
|
|
|
|
|
|
|
|
|
|
if (g_hash_table_contains (dir_size->icon_hash, icon_name))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
new_file.dir_index = dir_index;
|
|
|
|
|
new_file.best_suffix = best_suffix (suffixes, TRUE);
|
|
|
|
|
new_file.best_suffix_no_svg = best_suffix (suffixes, FALSE);
|
|
|
|
|
|
|
|
|
|
index = dir_size->icon_files->len;
|
|
|
|
|
g_array_append_val (dir_size->icon_files, new_file);
|
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
g_hash_table_insert (dir_size->icon_hash, (char *)icon_name, GINT_TO_POINTER(index));
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
/* Icon names are are already interned */
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
static void
|
|
|
|
|
theme_add_dir_with_icons (IconTheme *theme,
|
|
|
|
|
IconThemeDirSize *dir_size,
|
|
|
|
|
gboolean is_resource,
|
|
|
|
|
char *path /* takes ownership */,
|
|
|
|
|
GHashTable *icons)
|
|
|
|
|
{
|
|
|
|
|
GHashTableIter iter;
|
|
|
|
|
gpointer key, value;
|
|
|
|
|
guint32 dir_index;
|
|
|
|
|
|
2020-02-02 00:19:50 +00:00
|
|
|
|
dir_index = theme_add_icon_dir (theme, is_resource, path);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, icons);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
|
|
|
{
|
2020-02-07 10:54:00 +00:00
|
|
|
|
const char *icon_name = key; /* interned */
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
guint suffixes = GPOINTER_TO_INT(value);
|
|
|
|
|
theme_add_icon_file (theme, icon_name, suffixes, dir_size, dir_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
static void
|
2019-09-08 12:57:40 +00:00
|
|
|
|
theme_subdir_load (GtkIconTheme *self,
|
2014-06-19 23:42:53 +00:00
|
|
|
|
IconTheme *theme,
|
|
|
|
|
GKeyFile *theme_file,
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *subdir)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *type_string;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
IconThemeDirType type;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size;
|
|
|
|
|
int min_size;
|
|
|
|
|
int max_size;
|
|
|
|
|
int threshold;
|
2004-10-24 05:48:16 +00:00
|
|
|
|
GError *error = NULL;
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
guint32 dir_size_index;
|
|
|
|
|
IconThemeDirSize *dir_size;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int scale;
|
2020-04-25 18:18:29 +00:00
|
|
|
|
guint i;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2004-10-24 05:48:16 +00:00
|
|
|
|
size = g_key_file_get_integer (theme_file, subdir, "Size", &error);
|
|
|
|
|
if (error)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2004-10-24 05:48:16 +00:00
|
|
|
|
g_error_free (error);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
g_warning ("Theme directory %s of theme %s has no size field\n",
|
2014-06-19 23:42:53 +00:00
|
|
|
|
subdir, theme->name);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2019-09-01 08:04:32 +00:00
|
|
|
|
|
2003-07-02 22:44:09 +00:00
|
|
|
|
type = ICON_THEME_DIR_THRESHOLD;
|
2004-10-24 05:48:16 +00:00
|
|
|
|
type_string = g_key_file_get_string (theme_file, subdir, "Type", NULL);
|
|
|
|
|
if (type_string)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
if (strcmp (type_string, "Fixed") == 0)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
type = ICON_THEME_DIR_FIXED;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
else if (strcmp (type_string, "Scalable") == 0)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
type = ICON_THEME_DIR_SCALABLE;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
else if (strcmp (type_string, "Threshold") == 0)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
type = ICON_THEME_DIR_THRESHOLD;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
g_free (type_string);
|
|
|
|
|
}
|
2019-09-01 08:04:32 +00:00
|
|
|
|
|
2011-06-01 00:29:53 +00:00
|
|
|
|
if (g_key_file_has_key (theme_file, subdir, "MaxSize", NULL))
|
|
|
|
|
max_size = g_key_file_get_integer (theme_file, subdir, "MaxSize", NULL);
|
|
|
|
|
else
|
|
|
|
|
max_size = size;
|
2004-10-24 05:48:16 +00:00
|
|
|
|
|
2011-06-01 00:29:53 +00:00
|
|
|
|
if (g_key_file_has_key (theme_file, subdir, "MinSize", NULL))
|
|
|
|
|
min_size = g_key_file_get_integer (theme_file, subdir, "MinSize", NULL);
|
|
|
|
|
else
|
|
|
|
|
min_size = size;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2011-06-01 00:29:53 +00:00
|
|
|
|
if (g_key_file_has_key (theme_file, subdir, "Threshold", NULL))
|
|
|
|
|
threshold = g_key_file_get_integer (theme_file, subdir, "Threshold", NULL);
|
|
|
|
|
else
|
|
|
|
|
threshold = 2;
|
2004-11-02 02:07:30 +00:00
|
|
|
|
|
2013-08-19 13:41:49 +00:00
|
|
|
|
if (g_key_file_has_key (theme_file, subdir, "Scale", NULL))
|
|
|
|
|
scale = g_key_file_get_integer (theme_file, subdir, "Scale", NULL);
|
2013-05-10 16:06:00 +00:00
|
|
|
|
else
|
|
|
|
|
scale = 1;
|
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
dir_size_index = theme_ensure_dir_size (theme, type, size, min_size, max_size, threshold, scale);
|
|
|
|
|
dir_size = &g_array_index (theme->dir_sizes, IconThemeDirSize, dir_size_index);
|
|
|
|
|
|
2020-04-25 18:18:29 +00:00
|
|
|
|
for (i = 0; i < self->dir_mtimes->len; i++)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-04-25 18:18:29 +00:00
|
|
|
|
IconThemeDirMtime *dir_mtime = &g_array_index (self->dir_mtimes, IconThemeDirMtime, i);
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *full_dir;
|
2004-11-02 02:07:30 +00:00
|
|
|
|
|
2015-02-23 20:49:08 +00:00
|
|
|
|
if (!dir_mtime->exists)
|
2014-06-19 23:42:53 +00:00
|
|
|
|
continue; /* directory doesn't exist */
|
2004-10-19 18:45:41 +00:00
|
|
|
|
|
2014-06-20 04:35:57 +00:00
|
|
|
|
full_dir = g_build_filename (dir_mtime->dir, subdir, NULL);
|
2004-10-19 18:45:41 +00:00
|
|
|
|
|
|
|
|
|
/* First, see if we have a cache for the directory */
|
2005-04-06 03:34:38 +00:00
|
|
|
|
if (dir_mtime->cache != NULL || g_file_test (full_dir, G_FILE_TEST_IS_DIR))
|
2014-06-19 23:42:53 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
GHashTable *icons = NULL;
|
2019-09-01 08:04:32 +00:00
|
|
|
|
|
2014-06-19 23:42:53 +00:00
|
|
|
|
if (dir_mtime->cache == NULL)
|
|
|
|
|
{
|
|
|
|
|
/* This will return NULL if the cache doesn't exist or is outdated */
|
2018-02-01 15:05:58 +00:00
|
|
|
|
dir_mtime->cache = gtk_icon_cache_new_for_path (dir_mtime->dir);
|
2014-06-19 23:42:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-01 08:04:32 +00:00
|
|
|
|
if (dir_mtime->cache != NULL)
|
2020-02-07 10:54:00 +00:00
|
|
|
|
icons = gtk_icon_cache_list_icons_in_directory (dir_mtime->cache, subdir, &theme->icons);
|
2019-09-01 08:04:32 +00:00
|
|
|
|
else
|
2020-02-07 10:54:00 +00:00
|
|
|
|
icons = scan_directory (self, full_dir, &theme->icons);
|
2019-09-01 08:04:32 +00:00
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (icons)
|
2007-12-03 17:44:27 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
theme_add_dir_with_icons (theme,
|
|
|
|
|
dir_size,
|
|
|
|
|
FALSE,
|
|
|
|
|
g_steal_pointer (&full_dir),
|
|
|
|
|
icons);
|
|
|
|
|
g_hash_table_destroy (icons);
|
2007-12-03 17:44:27 +00:00
|
|
|
|
}
|
2014-06-19 23:42:53 +00:00
|
|
|
|
}
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
|
|
|
|
|
g_free (full_dir);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
2014-06-20 04:35:57 +00:00
|
|
|
|
|
2014-07-10 01:12:08 +00:00
|
|
|
|
if (strcmp (theme->name, FALLBACK_ICON_THEME) == 0)
|
2019-09-01 07:26:16 +00:00
|
|
|
|
{
|
2020-04-25 18:18:29 +00:00
|
|
|
|
int r;
|
|
|
|
|
for (r = 0; self->resource_path[r]; r++)
|
2014-06-30 20:03:03 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
GHashTable *icons;
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *full_dir;
|
2019-09-01 07:26:16 +00:00
|
|
|
|
|
2017-11-13 17:12:52 +00:00
|
|
|
|
/* Force a trailing / here, to avoid extra copies in GResource */
|
2020-04-25 18:18:29 +00:00
|
|
|
|
full_dir = g_build_filename (self->resource_path[r], subdir, " ", NULL);
|
2017-11-13 17:12:52 +00:00
|
|
|
|
full_dir[strlen (full_dir) - 1] = '\0';
|
2019-09-01 07:26:16 +00:00
|
|
|
|
|
2020-02-07 10:54:00 +00:00
|
|
|
|
icons = scan_resource_directory (self, full_dir, &theme->icons);
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
if (icons)
|
2019-09-01 07:26:16 +00:00
|
|
|
|
{
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
theme_add_dir_with_icons (theme,
|
|
|
|
|
dir_size,
|
|
|
|
|
TRUE,
|
|
|
|
|
g_steal_pointer (&full_dir),
|
|
|
|
|
icons);
|
|
|
|
|
g_hash_table_destroy (icons);
|
2019-09-01 07:26:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
IconTheme: Make icon lookups faster
Traditionally the icon lookup for a theme has been:
lookup (icon_name, size):
best_directory = NULL
forearch theme
foreach directory in theme
if dir_size_matches (directory, size) && dir_has_icon (directory, icon-name)
best_directory = chose_best_size_dir (best_directory, directory)
if best_directory
return icon from best_directory
However, it turns out that there are a lot of subdirectories which have the same
size, as they differ only in the (essentially useless) "context" value. For example
the "16x16/apps" subdirectory is essentially the same as the "16x16/actions" one.
So, instead rathern than keeping all the directories as separate we store the
all the directories with the same size as a single entity (DirSize) and the
icon lookup in that DirSize looks up not only which suffix to use for that icon
but also which subdir it is in.
Additionally we keep a hashtable with all icon names that are
available in the entire theme (i.e. all DirSizes), which allows use
both to store each icon name only once, but also to do a quick
negative lookup and early exit in case we're looking up an icon that
doesn't exist. This is pretty common because we often look up sets of
icons like "image-png-symbolic", "image-png", "image", expecting some
to fail.
This brings down the time of the initial css validation from 20msec to 15msec for
me when running icon-factory.
2020-02-03 09:35:45 +00:00
|
|
|
|
g_free (full_dir);
|
2014-06-30 20:03:03 +00:00
|
|
|
|
}
|
2014-06-20 04:35:57 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* GtkIconPaintable
|
2003-07-02 22:44:09 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
static void icon_paintable_init (GdkPaintableInterface *iface);
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
2020-02-10 11:51:27 +00:00
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
PROP_0,
|
|
|
|
|
PROP_FILE,
|
|
|
|
|
PROP_ICON_NAME,
|
|
|
|
|
PROP_IS_SYMBOLIC,
|
|
|
|
|
};
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GtkIconPaintable, gtk_icon_paintable, G_TYPE_OBJECT,
|
2020-01-27 12:59:34 +00:00
|
|
|
|
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon_paintable_init))
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2013-02-13 14:05:02 +00:00
|
|
|
|
static void
|
2020-02-04 16:19:22 +00:00
|
|
|
|
gtk_icon_paintable_init (GtkIconPaintable *icon)
|
2013-02-13 14:05:02 +00:00
|
|
|
|
{
|
2020-01-29 10:08:02 +00:00
|
|
|
|
g_mutex_init (&icon->texture_lock);
|
2013-02-13 14:05:02 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
static GtkIconPaintable *
|
2020-02-10 10:40:00 +00:00
|
|
|
|
icon_paintable_new (const char *icon_name,
|
|
|
|
|
int desired_size,
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
int desired_scale)
|
2013-02-13 14:05:02 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon;
|
2013-09-23 10:37:36 +00:00
|
|
|
|
|
2020-02-10 11:51:27 +00:00
|
|
|
|
icon = g_object_new (GTK_TYPE_ICON_PAINTABLE,
|
|
|
|
|
"icon-name", icon_name,
|
|
|
|
|
NULL);
|
2013-09-23 10:37:36 +00:00
|
|
|
|
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
icon->desired_size = desired_size;
|
|
|
|
|
icon->desired_scale = desired_scale;
|
2013-09-23 10:37:36 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
return icon;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-13 14:05:02 +00:00
|
|
|
|
static void
|
2020-02-04 16:19:22 +00:00
|
|
|
|
gtk_icon_paintable_finalize (GObject *object)
|
2013-02-13 14:05:02 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon = (GtkIconPaintable *) object;
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
icon_cache_remove (icon);
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
g_strfreev (icon->key.icon_names);
|
2012-11-26 12:49:49 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
g_free (icon->filename);
|
2020-02-06 16:28:19 +00:00
|
|
|
|
g_free (icon->icon_name);
|
2012-10-28 19:01:30 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
g_clear_object (&icon->loadable);
|
|
|
|
|
g_clear_object (&icon->texture);
|
2020-02-05 16:08:29 +00:00
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
g_clear_object (&icon->win32_icon);
|
|
|
|
|
#endif
|
2005-08-19 04:39:30 +00:00
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
g_mutex_clear (&icon->texture_lock);
|
2020-01-24 16:46:57 +00:00
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
G_OBJECT_CLASS (gtk_icon_paintable_parent_class)->finalize (object);
|
2013-02-13 14:05:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-10 11:51:27 +00:00
|
|
|
|
static void
|
|
|
|
|
gtk_icon_paintable_get_property (GObject *object,
|
|
|
|
|
guint prop_id,
|
|
|
|
|
GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
GtkIconPaintable *icon = GTK_ICON_PAINTABLE (object);
|
|
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
|
{
|
|
|
|
|
case PROP_FILE:
|
|
|
|
|
g_value_take_object (value, gtk_icon_paintable_get_file (icon));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_ICON_NAME:
|
|
|
|
|
g_value_set_string (value, icon->icon_name);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_IS_SYMBOLIC:
|
|
|
|
|
g_value_set_boolean (value, icon->is_symbolic);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_icon_paintable_set_property (GObject *object,
|
|
|
|
|
guint prop_id,
|
|
|
|
|
const GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
GtkIconPaintable *icon = GTK_ICON_PAINTABLE (object);
|
|
|
|
|
GFile *file;
|
|
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
|
{
|
|
|
|
|
case PROP_FILE:
|
|
|
|
|
icon->is_resource = FALSE;
|
|
|
|
|
g_clear_pointer (&icon->filename, g_free);
|
|
|
|
|
|
|
|
|
|
file = G_FILE (g_value_get_object (value));
|
|
|
|
|
if (file)
|
|
|
|
|
{
|
|
|
|
|
icon->is_resource = g_file_has_uri_scheme (file, "resource");
|
|
|
|
|
if (icon->is_resource)
|
|
|
|
|
{
|
|
|
|
|
char *uri = g_file_get_uri (file);
|
|
|
|
|
icon->filename = g_strdup (uri + 11); /* resource:// */
|
|
|
|
|
g_free (uri);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
icon->filename = g_file_get_path (file);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_ICON_NAME:
|
|
|
|
|
g_free (icon->icon_name);
|
|
|
|
|
icon->icon_name = g_value_dup_string (value);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PROP_IS_SYMBOLIC:
|
|
|
|
|
icon->is_symbolic = g_value_get_boolean (value);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-02-13 14:05:02 +00:00
|
|
|
|
static void
|
2020-02-04 16:19:22 +00:00
|
|
|
|
gtk_icon_paintable_class_init (GtkIconPaintableClass *klass)
|
2013-02-13 14:05:02 +00:00
|
|
|
|
{
|
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
2020-02-10 11:51:27 +00:00
|
|
|
|
gobject_class->get_property = gtk_icon_paintable_get_property;
|
|
|
|
|
gobject_class->set_property = gtk_icon_paintable_set_property;
|
2020-02-04 16:19:22 +00:00
|
|
|
|
gobject_class->finalize = gtk_icon_paintable_finalize;
|
2020-02-10 11:51:27 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GtkIconPaintable:file:
|
|
|
|
|
*
|
|
|
|
|
* The file representing the icon, if any.
|
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class, PROP_FILE,
|
|
|
|
|
g_param_spec_object ("file",
|
|
|
|
|
P_("file"),
|
|
|
|
|
P_("The file representing the icon"),
|
|
|
|
|
G_TYPE_FILE,
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
|
|
|
|
|
/**
|
|
|
|
|
* GtkIconPaintable:icon-name:
|
|
|
|
|
*
|
|
|
|
|
* The icon name that was chosen during lookup.
|
|
|
|
|
*/
|
|
|
|
|
g_object_class_install_property (gobject_class, PROP_ICON_NAME,
|
|
|
|
|
g_param_spec_string ("icon-name",
|
|
|
|
|
P_("Icon name"),
|
2020-05-28 08:00:03 +00:00
|
|
|
|
P_("The icon name chosen during lookup"),
|
2020-02-10 11:51:27 +00:00
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
|
|
|
|
|
/**
|
|
|
|
|
* GtkIconPaintable:is-symbolic:
|
|
|
|
|
*
|
|
|
|
|
* Whether the icon is symbolic or not.
|
|
|
|
|
*/
|
2020-02-10 12:30:57 +00:00
|
|
|
|
g_object_class_install_property (gobject_class, PROP_IS_SYMBOLIC,
|
2020-02-10 11:51:27 +00:00
|
|
|
|
g_param_spec_boolean ("is-symbolic",
|
|
|
|
|
P_("Is symbolic"),
|
|
|
|
|
P_("If the icon is symbolic"),
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK));
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-10 11:33:17 +00:00
|
|
|
|
static GFile *
|
|
|
|
|
new_resource_file (const char *filename)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
2020-02-10 11:33:17 +00:00
|
|
|
|
char *escaped = g_uri_escape_string (filename,
|
|
|
|
|
G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
|
|
|
|
|
char *uri = g_strconcat ("resource://", escaped, NULL);
|
|
|
|
|
GFile *file = g_file_new_for_uri (uri);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-10 11:33:17 +00:00
|
|
|
|
g_free (escaped);
|
|
|
|
|
g_free (uri);
|
|
|
|
|
|
|
|
|
|
return file;
|
2020-02-06 16:33:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-02-10 11:33:17 +00:00
|
|
|
|
* gtk_icon_paintable_get_file:
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* @self: a #GtkIconPaintable
|
2020-02-06 16:33:19 +00:00
|
|
|
|
*
|
2020-02-10 11:33:17 +00:00
|
|
|
|
* Gets the #GFile that was used to load the icon, or %NULL if the icon was
|
|
|
|
|
* not loaded from a file.
|
2020-02-06 16:33:19 +00:00
|
|
|
|
*
|
2020-02-10 11:33:17 +00:00
|
|
|
|
* Returns: (nullable) (transfer full): the #GFile for the icon, or %NULL.
|
|
|
|
|
* Free with g_object_unref().
|
2020-02-06 16:33:19 +00:00
|
|
|
|
*/
|
2020-02-10 11:33:17 +00:00
|
|
|
|
GFile *
|
|
|
|
|
gtk_icon_paintable_get_file (GtkIconPaintable *icon)
|
2020-02-06 16:33:19 +00:00
|
|
|
|
{
|
2020-02-10 11:33:17 +00:00
|
|
|
|
if (icon->filename)
|
|
|
|
|
{
|
|
|
|
|
if (icon->is_resource)
|
|
|
|
|
return new_resource_file (icon->filename);
|
|
|
|
|
else
|
|
|
|
|
return g_file_new_for_path (icon->filename);
|
|
|
|
|
}
|
2020-02-06 16:33:19 +00:00
|
|
|
|
|
|
|
|
|
return NULL;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 16:28:19 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_paintable_get_icon_name:
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* @self: a #GtkIconPaintable
|
2020-02-06 16:28:19 +00:00
|
|
|
|
*
|
2020-02-10 10:40:00 +00:00
|
|
|
|
* Get the icon name being used for this icon.
|
|
|
|
|
*
|
|
|
|
|
* When an icon looked up in the icon theme was not available, the
|
|
|
|
|
* icon theme may use fallback icons - either those specified to
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* gtk_icon_theme_lookup_icon() or the always-available
|
2020-02-10 10:40:00 +00:00
|
|
|
|
* "image-missing". The icon chosen is returned by this function.
|
|
|
|
|
*
|
|
|
|
|
* If the icon was created without an icon theme, this function returns %NULL.
|
|
|
|
|
*
|
2020-02-06 16:28:19 +00:00
|
|
|
|
*
|
|
|
|
|
* Returns: (nullable) (type filename): the themed icon-name for the icon, or %NULL
|
|
|
|
|
* if its not a themed icon.
|
|
|
|
|
*/
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char *
|
2020-02-06 16:28:19 +00:00
|
|
|
|
gtk_icon_paintable_get_icon_name (GtkIconPaintable *icon)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (icon != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
return icon->icon_name;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-15 02:41:49 +00:00
|
|
|
|
/**
|
2020-02-04 16:19:22 +00:00
|
|
|
|
* gtk_icon_paintable_is_symbolic:
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* @self: a #GtkIconPaintable
|
2013-12-15 02:41:49 +00:00
|
|
|
|
*
|
|
|
|
|
* Checks if the icon is symbolic or not. This currently uses only
|
|
|
|
|
* the file name and not the file contents for determining this.
|
|
|
|
|
* This behaviour may change in the future.
|
|
|
|
|
*
|
2020-10-15 14:08:03 +00:00
|
|
|
|
* Note that to render a symbolic #GtkIconPaintable properly (with
|
|
|
|
|
* recoloring), you have to set its icon name on a #GtkImage.
|
|
|
|
|
*
|
2014-06-19 23:42:53 +00:00
|
|
|
|
* Returns: %TRUE if the icon is symbolic, %FALSE otherwise
|
|
|
|
|
*/
|
2013-12-15 02:41:49 +00:00
|
|
|
|
gboolean
|
2020-02-04 16:19:22 +00:00
|
|
|
|
gtk_icon_paintable_is_symbolic (GtkIconPaintable *icon)
|
2013-12-15 02:41:49 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_ICON_PAINTABLE (icon), FALSE);
|
2013-12-15 02:41:49 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
return icon->is_symbolic;
|
2013-12-15 02:41:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-18 12:22:11 +00:00
|
|
|
|
static GLoadableIcon *
|
2020-02-04 16:19:22 +00:00
|
|
|
|
icon_get_loadable (GtkIconPaintable *icon)
|
2019-10-18 12:22:11 +00:00
|
|
|
|
{
|
|
|
|
|
GFile *file;
|
|
|
|
|
GLoadableIcon *loadable;
|
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
if (icon->loadable)
|
|
|
|
|
return g_object_ref (icon->loadable);
|
2019-10-18 12:22:11 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
if (icon->is_resource)
|
2019-10-18 12:22:11 +00:00
|
|
|
|
{
|
2020-01-28 14:43:51 +00:00
|
|
|
|
char *uri = g_strconcat ("resource://", icon->filename, NULL);
|
2019-10-18 12:22:11 +00:00
|
|
|
|
file = g_file_new_for_uri (uri);
|
|
|
|
|
g_free (uri);
|
|
|
|
|
}
|
|
|
|
|
else
|
2020-01-28 14:43:51 +00:00
|
|
|
|
file = g_file_new_for_path (icon->filename);
|
2019-10-18 12:22:11 +00:00
|
|
|
|
|
|
|
|
|
loadable = G_LOADABLE_ICON (g_file_icon_new (file));
|
|
|
|
|
|
|
|
|
|
g_object_unref (file);
|
|
|
|
|
|
|
|
|
|
return loadable;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-29 14:33:49 +00:00
|
|
|
|
/* This function contains the complicated logic for deciding
|
2003-07-02 22:44:09 +00:00
|
|
|
|
* on the size at which to load the icon and loading it at
|
|
|
|
|
* that size.
|
|
|
|
|
*/
|
2020-02-05 16:08:29 +00:00
|
|
|
|
static void
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
icon_ensure_texture__locked (GtkIconPaintable *icon,
|
|
|
|
|
gboolean in_thread)
|
2003-07-02 22:44:09 +00:00
|
|
|
|
{
|
|
|
|
|
GdkPixbuf *source_pixbuf;
|
2020-01-29 10:33:30 +00:00
|
|
|
|
gint64 before;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int pixel_size;
|
2020-02-05 16:08:29 +00:00
|
|
|
|
GError *load_error = NULL;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
icon_cache_mark_used_if_cached (icon);
|
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
if (icon->texture)
|
2020-02-05 16:08:29 +00:00
|
|
|
|
return;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-08-19 22:49:34 +00:00
|
|
|
|
before = GDK_PROFILER_CURRENT_TIME;
|
2020-01-29 10:33:30 +00:00
|
|
|
|
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
/* This is the natural pixel size for the requested icon size + scale in this directory.
|
|
|
|
|
* We precalculate this so we can use it as a rasterization size for svgs.
|
2003-07-02 22:44:09 +00:00
|
|
|
|
*/
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
pixel_size = icon->desired_size * icon->desired_scale;
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
|
|
|
|
/* At this point, we need to actually get the icon; either from the
|
2007-03-23 14:06:52 +00:00
|
|
|
|
* builtin image or by loading the file
|
2003-07-02 22:44:09 +00:00
|
|
|
|
*/
|
2008-05-29 14:33:49 +00:00
|
|
|
|
source_pixbuf = NULL;
|
2020-02-05 16:08:29 +00:00
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
if (icon->win32_icon)
|
|
|
|
|
{
|
|
|
|
|
source_pixbuf = g_object_ref (icon->win32_icon);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
if (icon->is_resource)
|
2014-06-20 04:35:57 +00:00
|
|
|
|
{
|
2020-01-28 14:43:51 +00:00
|
|
|
|
if (icon->is_svg)
|
2014-06-20 04:35:57 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
if (gtk_icon_paintable_is_symbolic (icon))
|
2020-01-28 14:43:51 +00:00
|
|
|
|
source_pixbuf = gtk_make_symbolic_pixbuf_from_resource (icon->filename,
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
pixel_size, pixel_size,
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon->desired_scale,
|
2020-02-05 16:08:29 +00:00
|
|
|
|
&load_error);
|
2016-01-29 22:27:35 +00:00
|
|
|
|
else
|
2020-01-28 14:43:51 +00:00
|
|
|
|
source_pixbuf = _gdk_pixbuf_new_from_resource_at_scale (icon->filename,
|
2019-10-15 23:05:52 +00:00
|
|
|
|
"svg",
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
pixel_size, pixel_size,
|
2020-02-05 16:08:29 +00:00
|
|
|
|
TRUE, &load_error);
|
2014-06-20 04:35:57 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2020-02-05 16:08:29 +00:00
|
|
|
|
source_pixbuf = _gdk_pixbuf_new_from_resource (icon->filename,
|
|
|
|
|
g_str_has_suffix (icon->filename, ".xpm") ? "xpm" : "png",
|
|
|
|
|
&load_error);
|
|
|
|
|
|
|
|
|
|
if (source_pixbuf == NULL)
|
|
|
|
|
{
|
|
|
|
|
g_warning ("Failed to load icon %s: %s", icon->filename, load_error->message);
|
|
|
|
|
g_clear_error (&load_error);
|
|
|
|
|
}
|
2014-06-20 04:35:57 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2019-10-18 12:22:11 +00:00
|
|
|
|
GLoadableIcon *loadable;
|
2008-05-29 14:33:49 +00:00
|
|
|
|
GInputStream *stream;
|
Update spec.
2005-03-15 Anders Carlsson <andersca@imendio.com>
* docs/iconcache.txt:
Update spec.
* gtk/gtkiconcache.c: (find_image_offset),
(_gtk_icon_cache_get_icon_flags), (_gtk_icon_cache_add_icons),
(_gtk_icon_cache_get_icon), (_gtk_icon_cache_get_icon_data):
* gtk/gtkiconcache.h:
Update to be able to fetch pixbuf data and icon metadata.
* gtk/gtkicontheme.c: (theme_lookup_icon), (gtk_icon_info_free),
(icon_info_ensure_scale_and_pixbuf):
Use new cache functions.
* gtk/updateiconcache.c: (foreach_remove_func), (load_icon_data),
(maybe_cache_image_data), (scan_directory), (write_pixdata),
(get_image_meta_data_size), (get_image_pixel_data_size),
(get_image_data_size), (get_single_node_size), (get_bucket_size),
(write_bucket), (main):
Update to write pixbuf data as well as information from .icon
files.
2005-03-15 13:18:25 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
loadable = icon_get_loadable (icon);
|
2019-10-18 12:22:11 +00:00
|
|
|
|
stream = g_loadable_icon_load (loadable,
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
pixel_size,
|
2008-05-29 14:33:49 +00:00
|
|
|
|
NULL, NULL,
|
2020-02-05 16:08:29 +00:00
|
|
|
|
&load_error);
|
2019-10-18 12:22:11 +00:00
|
|
|
|
g_object_unref (loadable);
|
|
|
|
|
|
2008-05-29 14:33:49 +00:00
|
|
|
|
if (stream)
|
|
|
|
|
{
|
2014-06-23 02:04:00 +00:00
|
|
|
|
/* SVG icons are a special case - we just immediately scale them
|
|
|
|
|
* to the desired size
|
|
|
|
|
*/
|
2020-01-28 14:43:51 +00:00
|
|
|
|
if (icon->is_svg)
|
2014-06-14 15:19:12 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
if (gtk_icon_paintable_is_symbolic (icon))
|
2020-01-28 14:43:51 +00:00
|
|
|
|
source_pixbuf = gtk_make_symbolic_pixbuf_from_path (icon->filename,
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
pixel_size, pixel_size,
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon->desired_scale,
|
2020-02-05 16:08:29 +00:00
|
|
|
|
&load_error);
|
2016-01-29 22:27:35 +00:00
|
|
|
|
else
|
2019-10-15 23:05:52 +00:00
|
|
|
|
source_pixbuf = _gdk_pixbuf_new_from_stream_at_scale (stream,
|
|
|
|
|
"svg",
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
pixel_size, pixel_size,
|
2019-10-15 23:05:52 +00:00
|
|
|
|
TRUE, NULL,
|
2020-02-05 16:08:29 +00:00
|
|
|
|
&load_error);
|
2014-06-14 15:19:12 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2020-02-05 16:08:29 +00:00
|
|
|
|
source_pixbuf = _gdk_pixbuf_new_from_stream (stream,
|
|
|
|
|
g_str_has_suffix (icon->filename, ".xpm") ? "xpm" : "png",
|
|
|
|
|
NULL, &load_error);
|
2008-05-29 14:33:49 +00:00
|
|
|
|
g_object_unref (stream);
|
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
if (source_pixbuf == NULL)
|
2016-05-19 13:03:20 +00:00
|
|
|
|
{
|
2020-02-05 16:08:29 +00:00
|
|
|
|
g_warning ("Failed to load icon %s: %s", icon->filename, load_error->message);
|
|
|
|
|
g_clear_error (&load_error);
|
2016-05-19 13:03:20 +00:00
|
|
|
|
}
|
2020-02-05 16:08:29 +00:00
|
|
|
|
}
|
2016-05-19 13:03:20 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
if (!source_pixbuf)
|
|
|
|
|
{
|
|
|
|
|
source_pixbuf = _gdk_pixbuf_new_from_resource (IMAGE_MISSING_RESOURCE_PATH, "png", NULL);
|
2020-02-06 16:28:19 +00:00
|
|
|
|
icon->icon_name = g_strdup ("image-missing");
|
2020-02-05 16:08:29 +00:00
|
|
|
|
icon->is_symbolic = FALSE;
|
|
|
|
|
g_assert (source_pixbuf != NULL);
|
2016-05-19 13:03:20 +00:00
|
|
|
|
}
|
2008-05-29 14:33:49 +00:00
|
|
|
|
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
/* Actual scaling is done during rendering, so just keep the source pixbuf as a texture */
|
|
|
|
|
icon->texture = gdk_texture_new_for_pixbuf (source_pixbuf);
|
|
|
|
|
g_object_unref (source_pixbuf);
|
2003-07-02 22:44:09 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
g_assert (icon->texture != NULL);
|
2019-09-01 11:25:44 +00:00
|
|
|
|
|
2020-02-12 10:05:01 +00:00
|
|
|
|
if (GDK_PROFILER_IS_RUNNING)
|
2020-02-12 11:43:27 +00:00
|
|
|
|
{
|
2020-08-19 22:49:34 +00:00
|
|
|
|
gint64 end = GDK_PROFILER_CURRENT_TIME;
|
2020-02-12 11:43:27 +00:00
|
|
|
|
/* Don't report quick (< 0.5 msec) parses */
|
2020-08-19 22:49:34 +00:00
|
|
|
|
if (end - before > 500000 || !in_thread)
|
|
|
|
|
{
|
|
|
|
|
gdk_profiler_add_markf (before, (end - before), in_thread ? "icon load (thread)" : "icon load" ,
|
|
|
|
|
"%s size %d@%d", icon->filename, icon->desired_size, icon->desired_scale);
|
|
|
|
|
}
|
2020-02-12 11:43:27 +00:00
|
|
|
|
}
|
2003-07-02 22:44:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-06 16:14:44 +00:00
|
|
|
|
static GdkTexture *
|
|
|
|
|
gtk_icon_paintable_ensure_texture (GtkIconPaintable *self)
|
2020-01-27 12:59:34 +00:00
|
|
|
|
{
|
|
|
|
|
GdkTexture *texture = NULL;
|
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
g_mutex_lock (&self->texture_lock);
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
icon_ensure_texture__locked (self, FALSE);
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
2020-12-17 17:45:47 +00:00
|
|
|
|
texture = self->texture;
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
2020-01-29 10:08:02 +00:00
|
|
|
|
g_mutex_unlock (&self->texture_lock);
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
g_assert (texture != NULL);
|
|
|
|
|
|
2020-01-27 15:42:38 +00:00
|
|
|
|
return texture;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-28 11:06:55 +00:00
|
|
|
|
static void
|
|
|
|
|
init_color_matrix (graphene_matrix_t *color_matrix,
|
2020-07-04 07:26:08 +00:00
|
|
|
|
graphene_vec4_t *color_offset,
|
|
|
|
|
const GdkRGBA *foreground_color,
|
|
|
|
|
const GdkRGBA *success_color,
|
|
|
|
|
const GdkRGBA *warning_color,
|
|
|
|
|
const GdkRGBA *error_color)
|
2020-01-28 11:06:55 +00:00
|
|
|
|
{
|
2020-12-18 07:36:59 +00:00
|
|
|
|
const GdkRGBA fg_default = { 0.7450980392156863, 0.7450980392156863, 0.7450980392156863, 1.0};
|
|
|
|
|
const GdkRGBA success_default = { 0.3046921492332342,0.6015716792553597, 0.023437857633325704, 1.0};
|
|
|
|
|
const GdkRGBA warning_default = {0.9570458533607996, 0.47266346227206835, 0.2421911955443656, 1.0 };
|
|
|
|
|
const GdkRGBA error_default = { 0.796887159533074, 0 ,0, 1.0 };
|
2020-01-28 11:06:55 +00:00
|
|
|
|
const GdkRGBA *fg = foreground_color ? foreground_color : &fg_default;
|
|
|
|
|
const GdkRGBA *sc = success_color ? success_color : &success_default;
|
|
|
|
|
const GdkRGBA *wc = warning_color ? warning_color : &warning_default;
|
|
|
|
|
const GdkRGBA *ec = error_color ? error_color : &error_default;
|
|
|
|
|
|
|
|
|
|
graphene_matrix_init_from_float (color_matrix,
|
|
|
|
|
(float[16]) {
|
|
|
|
|
sc->red - fg->red, sc->green - fg->green, sc->blue - fg->blue, 0,
|
2020-01-30 07:53:46 +00:00
|
|
|
|
wc->red - fg->red, wc->green - fg->green, wc->blue - fg->blue, 0,
|
|
|
|
|
ec->red - fg->red, ec->green - fg->green, ec->blue - fg->blue, 0,
|
|
|
|
|
0, 0, 0, fg->alpha
|
|
|
|
|
});
|
2020-01-28 11:06:55 +00:00
|
|
|
|
graphene_vec4_init (color_offset, fg->red, fg->green, fg->blue, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-01-27 15:42:38 +00:00
|
|
|
|
static void
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon_paintable_snapshot (GdkPaintable *paintable,
|
2020-01-30 07:55:44 +00:00
|
|
|
|
GtkSnapshot *snapshot,
|
2020-01-29 10:08:02 +00:00
|
|
|
|
double width,
|
|
|
|
|
double height)
|
2020-01-27 15:42:38 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon = GTK_ICON_PAINTABLE (paintable);
|
2020-01-27 15:42:38 +00:00
|
|
|
|
|
2020-02-05 08:49:23 +00:00
|
|
|
|
gtk_icon_paintable_snapshot_with_colors (icon, snapshot, width, height,
|
|
|
|
|
NULL, NULL, NULL, NULL);
|
2020-01-27 15:42:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-30 09:44:12 +00:00
|
|
|
|
/**
|
2020-02-04 16:19:22 +00:00
|
|
|
|
* gtk_icon_paintable_snapshot_with_colors:
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* @icon: a #GtkIconPaintable
|
2020-01-30 09:44:12 +00:00
|
|
|
|
* @snapshot: a #GdkSnapshot to snapshot to
|
|
|
|
|
* @width: width to snapshot in
|
|
|
|
|
* @height: height to snapshot in
|
|
|
|
|
* @foreground_color: (allow-none): a #GdkRGBA representing the foreground color
|
|
|
|
|
* of the icon or %NULL to use the default color.
|
|
|
|
|
* @success_color: (allow-none): a #GdkRGBA representing the warning color
|
|
|
|
|
* of the icon or %NULL to use the default color
|
|
|
|
|
* @warning_color: (allow-none): a #GdkRGBA representing the warning color
|
|
|
|
|
* of the icon or %NULL to use the default color
|
|
|
|
|
* @error_color: (allow-none): a #GdkRGBA representing the error color
|
|
|
|
|
* of the icon or %NULL to use the default color (allow-none)
|
|
|
|
|
*
|
|
|
|
|
* This is similar to the implementation of gdk_paintable_snapshot(), but if the icon is
|
2020-06-18 07:47:16 +00:00
|
|
|
|
* symbolic it will be recolored with the specified colors (which usually comes from the theme).
|
2020-01-30 09:44:12 +00:00
|
|
|
|
*/
|
2020-01-27 15:42:38 +00:00
|
|
|
|
void
|
2020-02-04 16:19:22 +00:00
|
|
|
|
gtk_icon_paintable_snapshot_with_colors (GtkIconPaintable *icon,
|
2020-02-05 08:30:47 +00:00
|
|
|
|
GtkSnapshot *snapshot,
|
|
|
|
|
double width,
|
|
|
|
|
double height,
|
|
|
|
|
const GdkRGBA *foreground_color,
|
|
|
|
|
const GdkRGBA *success_color,
|
|
|
|
|
const GdkRGBA *warning_color,
|
|
|
|
|
const GdkRGBA *error_color)
|
2020-01-27 15:42:38 +00:00
|
|
|
|
{
|
|
|
|
|
GdkTexture *texture;
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
int texture_width, texture_height;
|
|
|
|
|
double render_width;
|
|
|
|
|
double render_height;
|
2020-02-05 16:08:29 +00:00
|
|
|
|
gboolean symbolic;
|
2020-01-27 15:42:38 +00:00
|
|
|
|
|
2020-02-06 16:14:44 +00:00
|
|
|
|
texture = gtk_icon_paintable_ensure_texture (icon);
|
2020-02-05 16:08:29 +00:00
|
|
|
|
symbolic = gtk_icon_paintable_is_symbolic (icon);
|
2020-01-27 15:42:38 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
if (symbolic)
|
|
|
|
|
{
|
|
|
|
|
graphene_matrix_t matrix;
|
|
|
|
|
graphene_vec4_t offset;
|
2020-01-27 15:42:38 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
init_color_matrix (&matrix, &offset,
|
|
|
|
|
foreground_color, success_color,
|
|
|
|
|
warning_color, error_color);
|
2020-01-27 15:42:38 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
gtk_snapshot_push_color_matrix (snapshot, &matrix, &offset);
|
|
|
|
|
}
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
texture_width = gdk_texture_get_width (texture);
|
2020-02-10 12:12:26 +00:00
|
|
|
|
texture_height = gdk_texture_get_height (texture);
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
/* Keep aspect ratio and center */
|
|
|
|
|
if (texture_width >= texture_height)
|
|
|
|
|
{
|
|
|
|
|
render_width = width;
|
|
|
|
|
render_height = height * ((double)texture_height / texture_width);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
render_width = width * ((double)texture_width / texture_height);
|
|
|
|
|
render_height = height;
|
|
|
|
|
}
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
gtk_snapshot_append_texture (snapshot, texture,
|
|
|
|
|
&GRAPHENE_RECT_INIT ((width - render_width) / 2,
|
|
|
|
|
(height - render_height) / 2,
|
|
|
|
|
render_width,
|
2020-02-10 12:12:26 +00:00
|
|
|
|
render_height));
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
2020-02-05 16:08:29 +00:00
|
|
|
|
if (symbolic)
|
|
|
|
|
gtk_snapshot_pop (snapshot);
|
2020-01-27 12:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GdkPaintableFlags
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon_paintable_get_flags (GdkPaintable *paintable)
|
2020-01-27 12:59:34 +00:00
|
|
|
|
{
|
|
|
|
|
return GDK_PAINTABLE_STATIC_SIZE | GDK_PAINTABLE_STATIC_CONTENTS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon_paintable_get_intrinsic_width (GdkPaintable *paintable)
|
2020-01-27 12:59:34 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon = GTK_ICON_PAINTABLE (paintable);
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
return icon->desired_size;
|
2020-01-27 12:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon_paintable_get_intrinsic_height (GdkPaintable *paintable)
|
2020-01-27 12:59:34 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon = GTK_ICON_PAINTABLE (paintable);
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
IconTheme: Simplify icon scaling
We had a pretty complex setup where we tried to avoid scaling up themes from dirs
that specified a size. However, not only was it very complex, but it didn't quite
work with window scales, because when using e.g. a size 32 directory for 16@2x
the dir size is wrong anyway. Additionally it turns out most code either picks
an existing icon size, or uses the FORCE_SIZE flags, so it doesn't seem
like a useful behaviour.
This change drops the FORCE_SIZE flags, and always scales
icons. Additionally it moves the scaling of the icon to rendering,
which seems more modern, and allows us to (later) share icons loaded
for different sizes that happened to use the same source file (at
different scales).
Note that this changes the behaviour of
gtk_icon_paintable_download_texture() is it now returns the unscaled
source icon. However, ignore thats, as I plan to remove this function
and replace it with a way to render a paintable to a cairo-surface
instead.
2020-02-05 14:47:23 +00:00
|
|
|
|
return icon->desired_size;
|
2020-01-27 12:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon_paintable_init (GdkPaintableInterface *iface)
|
2020-01-27 12:59:34 +00:00
|
|
|
|
{
|
2020-01-28 14:43:51 +00:00
|
|
|
|
iface->snapshot = icon_paintable_snapshot;
|
|
|
|
|
iface->get_flags = icon_paintable_get_flags;
|
|
|
|
|
iface->get_intrinsic_width = icon_paintable_get_intrinsic_width;
|
|
|
|
|
iface->get_intrinsic_height = icon_paintable_get_intrinsic_height;
|
2020-01-27 12:59:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-10 11:57:27 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_paintable_new_for_file:
|
|
|
|
|
* @file: a #GFile
|
|
|
|
|
* @size: desired icon size
|
|
|
|
|
* @scale: the desired scale
|
|
|
|
|
*
|
|
|
|
|
* Creates a #GtkIconPaintable for a file with a given size and scale
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* #GtkIconPaintable. The icon can then be rendered by using it as a #GdkPaintable.
|
2020-02-10 11:57:27 +00:00
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer full): a #GtkIconPaintable containing
|
|
|
|
|
* for the icon. Unref with g_object_unref()
|
|
|
|
|
*/
|
|
|
|
|
GtkIconPaintable *
|
2020-02-04 16:19:22 +00:00
|
|
|
|
gtk_icon_paintable_new_for_file (GFile *file,
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size,
|
|
|
|
|
int scale)
|
2018-10-30 15:31:09 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon;
|
2018-10-30 15:31:09 +00:00
|
|
|
|
|
2020-02-10 10:40:00 +00:00
|
|
|
|
icon = icon_paintable_new (NULL, size, scale);
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon->loadable = G_LOADABLE_ICON (g_file_icon_new (file));
|
|
|
|
|
icon->is_resource = g_file_has_uri_scheme (file, "resource");
|
2018-10-30 15:31:09 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
if (icon->is_resource)
|
2018-10-30 15:31:09 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
char *uri;
|
2018-10-30 15:31:09 +00:00
|
|
|
|
|
|
|
|
|
uri = g_file_get_uri (file);
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon->filename = g_strdup (uri + 11); /* resource:// */
|
2018-10-30 15:31:09 +00:00
|
|
|
|
g_free (uri);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon->filename = g_file_get_path (file);
|
2018-10-30 15:31:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-04 08:35:20 +00:00
|
|
|
|
icon->is_svg = suffix_from_name (icon->filename) == ICON_CACHE_FLAG_SVG_SUFFIX;
|
2018-10-30 15:31:09 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
return icon;
|
2018-10-30 15:31:09 +00:00
|
|
|
|
}
|
2013-05-10 16:06:00 +00:00
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
static GtkIconPaintable *
|
|
|
|
|
gtk_icon_paintable_new_for_pixbuf (GtkIconTheme *icon_theme,
|
2020-02-06 08:45:03 +00:00
|
|
|
|
GdkPixbuf *pixbuf,
|
|
|
|
|
int size,
|
|
|
|
|
int scale)
|
2019-10-18 13:47:07 +00:00
|
|
|
|
{
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *icon;
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int width, height;
|
2020-01-27 12:59:34 +00:00
|
|
|
|
|
2020-02-06 08:45:03 +00:00
|
|
|
|
if (size <= 0)
|
|
|
|
|
{
|
|
|
|
|
width = gdk_pixbuf_get_width (pixbuf);
|
|
|
|
|
height = gdk_pixbuf_get_height (pixbuf);
|
|
|
|
|
size = MAX (width, height);
|
|
|
|
|
}
|
2019-10-18 13:47:07 +00:00
|
|
|
|
|
2020-02-10 10:40:00 +00:00
|
|
|
|
icon = icon_paintable_new (NULL, size, scale);
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon->texture = gdk_texture_new_for_pixbuf (pixbuf);
|
2019-10-18 13:47:07 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
return icon;
|
2019-10-18 13:47:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-05-10 16:06:00 +00:00
|
|
|
|
/**
|
2020-01-28 15:14:52 +00:00
|
|
|
|
* gtk_icon_theme_lookup_by_gicon:
|
2019-09-08 12:57:40 +00:00
|
|
|
|
* @self: a #GtkIconTheme
|
2013-05-10 16:06:00 +00:00
|
|
|
|
* @icon: the #GIcon to look up
|
|
|
|
|
* @size: desired icon size
|
|
|
|
|
* @scale: the desired scale
|
2020-02-01 23:27:14 +00:00
|
|
|
|
* @direction: text direction the icon will be displayed in
|
2013-05-10 16:06:00 +00:00
|
|
|
|
* @flags: flags modifying the behavior of the icon lookup
|
|
|
|
|
*
|
2020-01-30 09:44:12 +00:00
|
|
|
|
* Looks up a icon for a desired size and window scale, returning a
|
2020-05-11 16:47:20 +00:00
|
|
|
|
* #GtkIconPaintable. The icon can then be rendered by using it as a #GdkPaintable,
|
2020-01-30 09:44:12 +00:00
|
|
|
|
* or you can get information such as the filename and size.
|
2013-05-10 16:06:00 +00:00
|
|
|
|
*
|
2020-02-06 09:17:13 +00:00
|
|
|
|
* Returns: (transfer full): a #GtkIconPaintable containing
|
|
|
|
|
* information about the icon. Unref with g_object_unref()
|
2013-05-10 16:06:00 +00:00
|
|
|
|
*/
|
2020-02-04 16:19:22 +00:00
|
|
|
|
GtkIconPaintable *
|
2020-01-28 15:14:52 +00:00
|
|
|
|
gtk_icon_theme_lookup_by_gicon (GtkIconTheme *self,
|
|
|
|
|
GIcon *gicon,
|
2020-07-24 13:54:49 +00:00
|
|
|
|
int size,
|
|
|
|
|
int scale,
|
2020-02-01 23:27:14 +00:00
|
|
|
|
GtkTextDirection direction,
|
2020-01-28 15:14:52 +00:00
|
|
|
|
GtkIconLookupFlags flags)
|
2008-05-29 14:33:49 +00:00
|
|
|
|
{
|
2020-02-06 08:45:03 +00:00
|
|
|
|
GtkIconPaintable *icon = NULL;
|
2008-05-29 14:33:49 +00:00
|
|
|
|
|
2019-09-08 12:57:40 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
|
2020-01-28 14:43:51 +00:00
|
|
|
|
g_return_val_if_fail (G_IS_ICON (gicon), NULL);
|
2008-05-29 14:33:49 +00:00
|
|
|
|
|
2020-02-06 09:26:26 +00:00
|
|
|
|
/* We can't render emblemed icons atm, but at least render the base */
|
|
|
|
|
while (G_IS_EMBLEMED_ICON (gicon))
|
|
|
|
|
gicon = g_emblemed_icon_get_icon (G_EMBLEMED_ICON (gicon));
|
2020-03-05 06:02:24 +00:00
|
|
|
|
g_assert (gicon); /* shut up gcc -Wnull-dereference */
|
2020-02-06 09:26:26 +00:00
|
|
|
|
|
2020-01-28 14:43:51 +00:00
|
|
|
|
if (GDK_IS_PIXBUF (gicon))
|
2013-08-01 21:06:00 +00:00
|
|
|
|
{
|
2020-02-06 08:45:03 +00:00
|
|
|
|
GdkPixbuf *pixbuf = GDK_PIXBUF (gicon);
|
2013-08-01 21:06:00 +00:00
|
|
|
|
|
2020-02-06 08:45:03 +00:00
|
|
|
|
icon = gtk_icon_paintable_new_for_pixbuf (self, pixbuf, size, scale);
|
2016-01-14 17:53:50 +00:00
|
|
|
|
}
|
2020-01-28 14:43:51 +00:00
|
|
|
|
else if (G_IS_FILE_ICON (gicon))
|
2016-01-14 17:53:50 +00:00
|
|
|
|
{
|
2020-01-28 14:43:51 +00:00
|
|
|
|
GFile *file = g_file_icon_get_file (G_FILE_ICON (gicon));
|
2016-01-14 17:53:50 +00:00
|
|
|
|
|
2020-02-04 16:19:22 +00:00
|
|
|
|
icon = gtk_icon_paintable_new_for_file (file, size, scale);
|
2013-08-01 21:06:00 +00:00
|
|
|
|
}
|
2020-01-28 14:43:51 +00:00
|
|
|
|
else if (G_IS_LOADABLE_ICON (gicon))
|
2008-05-29 14:33:49 +00:00
|
|
|
|
{
|
2020-02-10 10:40:00 +00:00
|
|
|
|
icon = icon_paintable_new (NULL, size, scale);
|
2020-01-28 14:43:51 +00:00
|
|
|
|
icon->loadable = G_LOADABLE_ICON (g_object_ref (gicon));
|
|
|
|
|
icon->is_svg = FALSE;
|
2008-05-29 14:33:49 +00:00
|
|
|
|
}
|
2020-01-28 14:43:51 +00:00
|
|
|
|
else if (G_IS_THEMED_ICON (gicon))
|
2008-05-29 14:33:49 +00:00
|
|
|
|
{
|
2020-07-24 18:40:36 +00:00
|
|
|
|
const char **names;
|
2008-05-29 14:33:49 +00:00
|
|
|
|
|
2020-07-24 18:40:36 +00:00
|
|
|
|
names = (const char **) g_themed_icon_get_names (G_THEMED_ICON (gicon));
|
2020-02-04 02:53:22 +00:00
|
|
|
|
icon = gtk_icon_theme_lookup_icon (self, names[0], &names[1], size, scale, direction, flags);
|
2008-05-29 14:33:49 +00:00
|
|
|
|
}
|
2020-02-06 09:17:13 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2020-02-07 07:44:29 +00:00
|
|
|
|
g_debug ("Unhandled GIcon type %s", G_OBJECT_TYPE_NAME (gicon));
|
2020-02-10 10:40:00 +00:00
|
|
|
|
icon = icon_paintable_new ("image-missing", size, scale);
|
2020-02-06 09:17:13 +00:00
|
|
|
|
icon->filename = g_strdup (IMAGE_MISSING_RESOURCE_PATH);
|
|
|
|
|
icon->is_resource = TRUE;
|
|
|
|
|
}
|
2008-05-29 14:33:49 +00:00
|
|
|
|
|
2020-02-06 08:45:03 +00:00
|
|
|
|
return icon;
|
2008-05-29 14:33:49 +00:00
|
|
|
|
}
|
2020-10-03 15:25:35 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_icon_theme_get_display:
|
|
|
|
|
* @self: a #GtkIconTheme
|
|
|
|
|
*
|
|
|
|
|
* Returns the display that the GtkIconTheme object was
|
|
|
|
|
* created for.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (nullable) (transfer none): the display of @icon_theme
|
|
|
|
|
*/
|
|
|
|
|
GdkDisplay *
|
|
|
|
|
gtk_icon_theme_get_display (GtkIconTheme *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (GTK_IS_ICON_THEME (self), NULL);
|
|
|
|
|
|
|
|
|
|
return self->display;
|
|
|
|
|
}
|
|
|
|
|
|