diff options
author | William Jon McCann <jmccann@redhat.com> | 2012-09-11 16:50:20 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2012-09-16 20:20:44 -0400 |
commit | 1f5dea9eba4de5a54e9370fe8e4b90e6c0cec200 (patch) | |
tree | d6d730f4658a3ee101a746c23623b7dd72c6a85e /gtk/gtkcssprovider.c | |
parent | 5debed5ae247c1dd440cb71d0a6d328df74b0844 (diff) | |
download | gtk+-1f5dea9eba4de5a54e9370fe8e4b90e6c0cec200.tar.gz |
Bind the themes to the lifecycle of the screen
https://bugzilla.gnome.org/show_bug.cgi?id=683896
Diffstat (limited to 'gtk/gtkcssprovider.c')
-rw-r--r-- | gtk/gtkcssprovider.c | 311 |
1 files changed, 176 insertions, 135 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) { |