summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk/gtkcssprovider.c311
-rw-r--r--gtk/gtkcssprovider.h3
-rw-r--r--gtk/gtkcssproviderprivate.h7
-rw-r--r--gtk/gtksettings.c8
4 files changed, 187 insertions, 142 deletions
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index d4a3196a56..f91dbbe3eb 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -2607,155 +2607,99 @@ _gtk_css_provider_load_from_resource (GtkCssProvider *css_provider,
return result;
}
-/**
- * gtk_css_provider_get_default:
- *
- * Returns the provider containing the style settings used as a
- * fallback for all widgets.
- *
- * Returns: (transfer none): The provider used for fallback styling.
- * This memory is owned by GTK+, and you must not free it.
- **/
-GtkCssProvider *
-gtk_css_provider_get_default (void)
-{
- static GtkCssProvider *provider;
-
- if (G_UNLIKELY (!provider))
- {
- provider = gtk_css_provider_new ();
- }
-
- return provider;
-}
-
-gchar *
-_gtk_css_provider_get_theme_dir (void)
+static char *
+_find_theme_path (const gchar *name,
+ const gchar *variant)
{
- const gchar *var;
- gchar *path;
-
- var = g_getenv ("GTK_DATA_PREFIX");
+ gchar *subpath;
+ gchar *path = NULL;
- if (var)
- path = g_build_filename (var, "share", "themes", NULL);
+ if (variant)
+ subpath = g_strdup_printf ("gtk-3.0" G_DIR_SEPARATOR_S "gtk-%s.css", variant);
else
- path = g_build_filename (_gtk_get_data_prefix (), "share", "themes", NULL);
+ subpath = g_strdup ("gtk-3.0" G_DIR_SEPARATOR_S "gtk.css");
- return path;
-}
-
-/**
- * gtk_css_provider_get_named:
- * @name: A theme name
- * @variant: (allow-none): variant to load, for example, "dark", or
- * %NULL for the default
- *
- * Loads a theme from the usual theme paths
- *
- * Returns: (transfer none): a #GtkCssProvider with the theme loaded.
- * This memory is owned by GTK+, and you must not free it.
- */
-GtkCssProvider *
-gtk_css_provider_get_named (const gchar *name,
- const gchar *variant)
-{
- static GHashTable *themes = NULL;
- GtkCssProvider *provider;
- gchar *key;
-
- if (variant == NULL)
- key = (gchar *)name;
- else
- key = g_strconcat (name, "-", variant, NULL);
-
- if (G_UNLIKELY (!themes))
- themes = g_hash_table_new (g_str_hash, g_str_equal);
-
- provider = g_hash_table_lookup (themes, key);
+ /* First look in the user's config directory
+ */
+ path = g_build_filename (g_get_user_data_dir (), "themes", name, subpath, NULL);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ {
+ g_free (path);
+ path = NULL;
+ }
- if (!provider)
+ /* Next look in the user's home directory
+ */
+ if (!path)
{
- gchar *resource_path = NULL;
+ const gchar *home_dir;
- if (variant)
- resource_path = g_strdup_printf ("/org/gtk/libgtk/%s-%s.css", name, variant);
- else
- resource_path = g_strdup_printf ("/org/gtk/libgtk/%s.css", name);
+ home_dir = g_get_home_dir ();
+ if (home_dir)
+ {
+ path = g_build_filename (home_dir, ".themes", name, subpath, NULL);
- if (g_resources_get_info (resource_path, 0, NULL, NULL, NULL))
- {
- provider = gtk_css_provider_new ();
- if (!_gtk_css_provider_load_from_resource (provider, resource_path))
- {
- g_object_unref (provider);
- provider = NULL;
- }
- }
- g_free (resource_path);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ {
+ g_free (path);
+ path = NULL;
+ }
+ }
}
- if (!provider)
+ if (!path)
{
- gchar *subpath, *path = NULL;
+ gchar *theme_dir;
- if (variant)
- subpath = g_strdup_printf ("gtk-3.0" G_DIR_SEPARATOR_S "gtk-%s.css", variant);
- else
- subpath = g_strdup ("gtk-3.0" G_DIR_SEPARATOR_S "gtk.css");
+ theme_dir = _gtk_css_provider_get_theme_dir ();
+ path = g_build_filename (theme_dir, name, subpath, NULL);
+ g_free (theme_dir);
- /* First look in the user's config directory
- */
- path = g_build_filename (g_get_user_data_dir (), "themes", name, subpath, NULL);
if (!g_file_test (path, G_FILE_TEST_EXISTS))
{
g_free (path);
path = NULL;
}
+ }
- /* Next look in the user's home directory
- */
- if (!path)
- {
- const gchar *home_dir;
+ g_free (subpath);
- home_dir = g_get_home_dir ();
- if (home_dir)
- {
- path = g_build_filename (home_dir, ".themes", name, subpath, NULL);
+ return path;
+}
- if (!g_file_test (path, G_FILE_TEST_EXISTS))
- {
- g_free (path);
- path = NULL;
- }
- }
- }
+static gboolean
+_provider_load (GtkCssProvider *provider,
+ const gchar *name,
+ const gchar *variant)
+{
+ gchar *resource_path;
+ gboolean loaded = FALSE;
- if (!path)
- {
- gchar *theme_dir;
+ g_assert (provider != NULL);
- theme_dir = _gtk_css_provider_get_theme_dir ();
- path = g_build_filename (theme_dir, name, subpath, NULL);
- g_free (theme_dir);
+ if (variant)
+ resource_path = g_strdup_printf ("/org/gtk/libgtk/%s-%s.css", name, variant);
+ else
+ resource_path = g_strdup_printf ("/org/gtk/libgtk/%s.css", name);
- if (!g_file_test (path, G_FILE_TEST_EXISTS))
- {
- g_free (path);
- path = NULL;
- }
- }
+ if (g_resources_get_info (resource_path, 0, NULL, NULL, NULL))
+ {
+ loaded = _gtk_css_provider_load_from_resource (provider, resource_path);
+ }
+ g_free (resource_path);
- g_free (subpath);
+ if (!loaded)
+ {
+ char *path;
+
+ path = _find_theme_path (name, variant);
if (path)
{
- char *dir, *resource_file;
+ char *dir;
+ char *resource_file;
GResource *resource;
- provider = gtk_css_provider_new ();
-
dir = g_path_get_dirname (path);
resource_file = g_build_filename (dir, "gtk.gresource", NULL);
resource = g_resource_load (resource_file, NULL);
@@ -2764,34 +2708,131 @@ gtk_css_provider_get_named (const gchar *name,
if (resource != NULL)
g_resources_register (resource);
- if (!gtk_css_provider_load_from_path (provider, path, NULL))
+ loaded = gtk_css_provider_load_from_path (provider, path, NULL);
+ if (!loaded)
{
- if (resource != NULL)
- {
- g_resources_unregister (resource);
- g_resource_unref (resource);
- }
- g_object_unref (provider);
- provider = NULL;
+ if (resource != NULL)
+ {
+ g_resources_unregister (resource);
+ g_resource_unref (resource);
+ }
}
else
- {
- /* Only set this after load success, as load_from_path will clear it */
- provider->priv->resource = resource;
- g_hash_table_insert (themes, g_strdup (key), provider);
- }
+ {
+ /* Only set this after load success, as load_from_path will clear it */
+ provider->priv->resource = resource;
+ }
- g_free (path);
g_free (dir);
}
+ g_free (path);
+ }
+
+ return loaded;
+}
+
+static void
+destroy_theme_cache (GHashTable *themes)
+{
+ g_hash_table_destroy (themes);
+}
+
+/*
+ * _gtk_css_provider_get_named_for_screen:
+ * @screen: a #GdkScreen.
+ * @name: A theme name
+ * @variant: (allow-none): variant to load, for example, "dark", or
+ * %NULL for the default
+ *
+ * Loads a theme from the usual theme paths
+ *
+ * Returns: (transfer none): a #GtkCssProvider with the theme loaded.
+ * This memory is owned by GTK+, and you must not free it.
+ */
+GtkCssProvider *
+_gtk_css_provider_get_named_for_screen (GdkScreen *screen,
+ const gchar *name,
+ const gchar *variant)
+{
+ GtkCssProvider *provider;
+ GHashTable *themes;
+ gchar *key;
+
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ themes = g_object_get_data (G_OBJECT (screen), "gtk-themes");
+ if (G_UNLIKELY (!themes))
+ {
+ themes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ g_object_set_data_full (G_OBJECT (screen),
+ I_("gtk-themes"),
+ themes,
+ (GDestroyNotify)destroy_theme_cache);
}
- if (key != name)
- g_free (key);
+ if (name == NULL)
+ key = g_strdup ("");
+ else if (variant == NULL)
+ key = g_strdup (name);
+ else
+ key = g_strconcat (name, "-", variant, NULL);
+
+ provider = g_hash_table_lookup (themes, key);
+
+ if (!provider)
+ {
+ gboolean save = TRUE;
+
+ provider = gtk_css_provider_new ();
+
+ if (name != NULL)
+ save = _provider_load (provider, name, variant);
+
+ if (save)
+ g_hash_table_insert (themes, g_strdup (key), provider);
+ }
+
+ g_free (key);
return provider;
}
+/**
+ * gtk_css_provider_get_default:
+ *
+ * Returns the provider containing the style settings used as a
+ * fallback for all widgets.
+ *
+ * Returns: (transfer none): The provider used for fallback styling.
+ * This memory is owned by GTK+, and you must not free it.
+ **/
+GtkCssProvider *
+gtk_css_provider_get_default (void)
+{
+ GdkScreen *screen = gdk_screen_get_default ();
+
+ if (screen)
+ return _gtk_css_provider_get_named_for_screen (screen, NULL, NULL);
+ else
+ return NULL;
+}
+
+gchar *
+_gtk_css_provider_get_theme_dir (void)
+{
+ const gchar *var;
+ gchar *path;
+
+ var = g_getenv ("GTK_DATA_PREFIX");
+
+ if (var)
+ path = g_build_filename (var, "share", "themes", NULL);
+ else
+ path = g_build_filename (_gtk_get_data_prefix (), "share", "themes", NULL);
+
+ return path;
+}
+
static int
compare_properties (gconstpointer a, gconstpointer b, gpointer style)
{
diff --git a/gtk/gtkcssprovider.h b/gtk/gtkcssprovider.h
index db0222b580..6349d420c3 100644
--- a/gtk/gtkcssprovider.h
+++ b/gtk/gtkcssprovider.h
@@ -86,8 +86,7 @@ gboolean gtk_css_provider_load_from_path (GtkCssProvider *css_provider,
const gchar *path,
GError **error);
-GtkCssProvider * gtk_css_provider_get_default (void);
-
+GtkCssProvider * gtk_css_provider_get_default (void);
GtkCssProvider * gtk_css_provider_get_named (const gchar *name,
const gchar *variant);
diff --git a/gtk/gtkcssproviderprivate.h b/gtk/gtkcssproviderprivate.h
index 9a242547a8..240496a2e4 100644
--- a/gtk/gtkcssproviderprivate.h
+++ b/gtk/gtkcssproviderprivate.h
@@ -22,7 +22,12 @@
G_BEGIN_DECLS
-gchar *_gtk_css_provider_get_theme_dir (void);
+gchar * _gtk_css_provider_get_theme_dir (void);
+
+GtkCssProvider *_gtk_css_provider_get_named_for_screen (GdkScreen *screen,
+ const gchar *name,
+ const gchar *variant);
+
G_END_DECLS
diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c
index cfcc192484..b62534b7c9 100644
--- a/gtk/gtksettings.c
+++ b/gtk/gtksettings.c
@@ -2928,15 +2928,15 @@ settings_update_theme (GtkSettings *settings)
if (theme_name && *theme_name)
{
if (prefer_dark_theme)
- provider = gtk_css_provider_get_named (theme_name, "dark");
+ provider = _gtk_css_provider_get_named_for_screen (priv->screen, theme_name, "dark");
if (!provider)
- provider = gtk_css_provider_get_named (theme_name, NULL);
+ provider = _gtk_css_provider_get_named_for_screen (priv->screen, theme_name, NULL);
}
/* If we didn't find the named theme, fall back */
if (!provider)
- provider = gtk_css_provider_get_named ("Raleigh", NULL);
+ provider = _gtk_css_provider_get_named_for_screen (priv->screen, "Raleigh", NULL);
settings_update_provider (priv->screen, &priv->theme_provider, provider);
@@ -2971,7 +2971,7 @@ settings_update_key_theme (GtkSettings *settings)
NULL);
if (key_theme_name && *key_theme_name)
- provider = gtk_css_provider_get_named (key_theme_name, "keys");
+ provider = _gtk_css_provider_get_named_for_screen (priv->screen, key_theme_name, "keys");
settings_update_provider (priv->screen, &priv->key_theme_provider, provider);
g_free (key_theme_name);