diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js index 11a75c65e..fac21bf27 100644 --- a/js/ui/extensionSystem.js +++ b/js/ui/extensionSystem.js @@ -74,7 +74,7 @@ function disableExtension(uuid) { if (extension.stylesheet) { let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); - theme.unload_stylesheet(extension.stylesheet.get_path()); + theme.unload_stylesheet(extension.stylesheet); } try { @@ -118,7 +118,7 @@ function enableExtension(uuid) { let stylesheetFile = extension.dir.get_child(stylesheetNames[i]); if (stylesheetFile.query_exists(null)) { let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); - theme.load_stylesheet(stylesheetFile.get_path()); + theme.load_stylesheet(stylesheetFile); extension.stylesheet = stylesheetFile; break; } diff --git a/js/ui/main.js b/js/ui/main.js index f9bb59efb..994bbe478 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -228,8 +228,8 @@ function _loadDefaultStylesheet() { if (!sessionMode.isPrimary) return; - let stylesheet = global.datadir + '/theme/' + sessionMode.stylesheetName; - if (_defaultCssStylesheet == stylesheet) + let stylesheet = Gio.File.new_for_path(global.datadir + '/theme/' + sessionMode.stylesheetName); + if (_defaultCssStylesheet && _defaultCssStylesheet.equal(stylesheet)) return; _defaultCssStylesheet = stylesheet; @@ -256,7 +256,7 @@ function getThemeStylesheet() { * Set the theme CSS file that the shell will load */ function setThemeStylesheet(cssStylesheet) { - _cssStylesheet = cssStylesheet; + _cssStylesheet = Gio.File.new_for_path(cssStylesheet); } /** diff --git a/src/st/st-theme.c b/src/st/st-theme.c index 7eca7f8ea..2dab983b4 100644 --- a/src/st/st-theme.c +++ b/src/st/st-theme.c @@ -60,13 +60,13 @@ struct _StTheme { GObject parent; - char *application_stylesheet; - char *default_stylesheet; - char *theme_stylesheet; + GFile *application_stylesheet; + GFile *default_stylesheet; + GFile *theme_stylesheet; GSList *custom_stylesheets; - GHashTable *stylesheets_by_filename; - GHashTable *filenames_by_stylesheet; + GHashTable *stylesheets_by_file; + GHashTable *files_by_stylesheet; CRCascade *cascade; }; @@ -98,12 +98,25 @@ G_DEFINE_TYPE (StTheme, st_theme, G_TYPE_OBJECT) #define strqcmp(str,lit,lit_len) \ (strlen (str) != (lit_len) || memcmp (str, lit, lit_len)) +static gboolean +file_equal0 (GFile *file1, + GFile *file2) +{ + if (file1 == file2) + return TRUE; + + if ((file1 == NULL) || (file2 == NULL)) + return FALSE; + + return g_file_equal (file1, file2); +} + static void st_theme_init (StTheme *theme) { - theme->stylesheets_by_filename = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify)g_free, (GDestroyNotify)cr_stylesheet_unref); - theme->filenames_by_stylesheet = g_hash_table_new (g_direct_hash, g_direct_equal); + theme->stylesheets_by_file = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, + (GDestroyNotify)g_object_unref, (GDestroyNotify)cr_stylesheet_unref); + theme->files_by_stylesheet = g_hash_table_new (g_direct_hash, g_direct_equal); } static void @@ -124,10 +137,10 @@ st_theme_class_init (StThemeClass *klass) */ g_object_class_install_property (object_class, PROP_APPLICATION_STYLESHEET, - g_param_spec_string ("application-stylesheet", + g_param_spec_object ("application-stylesheet", "Application Stylesheet", "Stylesheet with application-specific styling", - NULL, + G_TYPE_FILE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); /** @@ -138,10 +151,10 @@ st_theme_class_init (StThemeClass *klass) */ g_object_class_install_property (object_class, PROP_THEME_STYLESHEET, - g_param_spec_string ("theme-stylesheet", + g_param_spec_object ("theme-stylesheet", "Theme Stylesheet", "Stylesheet with theme-specific styling", - NULL, + G_TYPE_FILE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); /** @@ -152,10 +165,10 @@ st_theme_class_init (StThemeClass *klass) */ g_object_class_install_property (object_class, PROP_DEFAULT_STYLESHEET, - g_param_spec_string ("default-stylesheet", + g_param_spec_object ("default-stylesheet", "Default Stylesheet", "Stylesheet with global default styling", - NULL, + G_TYPE_FILE, G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); signals[STYLESHEETS_CHANGED] = @@ -168,23 +181,32 @@ st_theme_class_init (StThemeClass *klass) } static CRStyleSheet * -parse_stylesheet (const char *filename, - GError **error) +parse_stylesheet (GFile *file, + GError **error) { enum CRStatus status; CRStyleSheet *stylesheet; + char *contents; + gsize length; - if (filename == NULL) + if (file == NULL) return NULL; - status = cr_om_parser_simply_parse_file ((const guchar *) filename, - CR_UTF_8, - &stylesheet); + if (!g_file_load_contents (file, NULL, &contents, &length, NULL, error)) + return NULL; + + status = cr_om_parser_simply_parse_buf ((const guchar *) contents, + length, + CR_UTF_8, + &stylesheet); + g_free (contents); if (status != CR_OK) { + char *uri = g_file_get_uri (file); g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Error parsing stylesheet '%s'; errcode:%d", filename, status); + "Error parsing stylesheet '%s'; errcode:%d", uri, status); + g_free (uri); return NULL; } @@ -203,12 +225,12 @@ _st_theme_parse_declaration_list (const char *str) /* Just g_warning for now until we have something nicer to do */ static CRStyleSheet * -parse_stylesheet_nofail (const char *filename) +parse_stylesheet_nofail (GFile *file) { GError *error = NULL; CRStyleSheet *result; - result = parse_stylesheet (filename, &error); + result = parse_stylesheet (file, &error); if (error) { g_warning ("%s", error->message); @@ -219,35 +241,33 @@ parse_stylesheet_nofail (const char *filename) static void insert_stylesheet (StTheme *theme, - const char *filename, + GFile *file, CRStyleSheet *stylesheet) { - char *filename_copy; - if (stylesheet == NULL) return; - filename_copy = g_strdup(filename); + g_object_ref (file); cr_stylesheet_ref (stylesheet); - g_hash_table_insert (theme->stylesheets_by_filename, filename_copy, stylesheet); - g_hash_table_insert (theme->filenames_by_stylesheet, stylesheet, filename_copy); + g_hash_table_insert (theme->stylesheets_by_file, file, stylesheet); + g_hash_table_insert (theme->files_by_stylesheet, stylesheet, file); } gboolean st_theme_load_stylesheet (StTheme *theme, - const char *path, + GFile *file, GError **error) { CRStyleSheet *stylesheet; - stylesheet = parse_stylesheet (path, error); + stylesheet = parse_stylesheet (file, error); if (!stylesheet) return FALSE; stylesheet->app_data = GUINT_TO_POINTER (TRUE); - insert_stylesheet (theme, path, stylesheet); + insert_stylesheet (theme, file, stylesheet); cr_stylesheet_ref (stylesheet); theme->custom_stylesheets = g_slist_prepend (theme->custom_stylesheets, stylesheet); g_signal_emit (theme, signals[STYLESHEETS_CHANGED], 0); @@ -257,11 +277,11 @@ st_theme_load_stylesheet (StTheme *theme, void st_theme_unload_stylesheet (StTheme *theme, - const char *path) + GFile *file) { CRStyleSheet *stylesheet; - stylesheet = g_hash_table_lookup (theme->stylesheets_by_filename, path); + stylesheet = g_hash_table_lookup (theme->stylesheets_by_file, file); if (!stylesheet) return; @@ -269,8 +289,8 @@ st_theme_unload_stylesheet (StTheme *theme, return; theme->custom_stylesheets = g_slist_remove (theme->custom_stylesheets, stylesheet); - g_hash_table_remove (theme->stylesheets_by_filename, path); - g_hash_table_remove (theme->filenames_by_stylesheet, stylesheet); + g_hash_table_remove (theme->stylesheets_by_file, file); + g_hash_table_remove (theme->files_by_stylesheet, stylesheet); cr_stylesheet_unref (stylesheet); g_signal_emit (theme, signals[STYLESHEETS_CHANGED], 0); } @@ -279,7 +299,7 @@ st_theme_unload_stylesheet (StTheme *theme, * st_theme_get_custom_stylesheets: * @theme: an #StTheme * - * Returns: (transfer full) (element-type utf8): the list of stylesheet filenames + * Returns: (transfer full) (element-type GFile): the list of stylesheet files * that were loaded with st_theme_load_stylesheet() */ GSList* @@ -291,9 +311,9 @@ st_theme_get_custom_stylesheets (StTheme *theme) for (iter = theme->custom_stylesheets; iter; iter = iter->next) { CRStyleSheet *stylesheet = iter->data; - gchar *filename = g_hash_table_lookup (theme->filenames_by_stylesheet, stylesheet); + GFile *file = g_hash_table_lookup (theme->files_by_stylesheet, stylesheet); - result = g_slist_prepend (result, g_strdup (filename)); + result = g_slist_prepend (result, g_object_ref (file)); } return result; @@ -334,12 +354,12 @@ st_theme_finalize (GObject * object) g_slist_free (theme->custom_stylesheets); theme->custom_stylesheets = NULL; - g_hash_table_destroy (theme->stylesheets_by_filename); - g_hash_table_destroy (theme->filenames_by_stylesheet); + g_hash_table_destroy (theme->stylesheets_by_file); + g_hash_table_destroy (theme->files_by_stylesheet); - g_free (theme->application_stylesheet); - g_free (theme->theme_stylesheet); - g_free (theme->default_stylesheet); + g_clear_object (&theme->application_stylesheet); + g_clear_object (&theme->theme_stylesheet); + g_clear_object (&theme->default_stylesheet); if (theme->cascade) { @@ -362,36 +382,39 @@ st_theme_set_property (GObject *object, { case PROP_APPLICATION_STYLESHEET: { - const char *path = g_value_get_string (value); + GFile *file = g_value_get_object (value); - if (path != theme->application_stylesheet) + if (!file_equal0 (file, theme->application_stylesheet)) { - g_free (theme->application_stylesheet); - theme->application_stylesheet = g_strdup (path); + g_clear_object (&theme->application_stylesheet); + if (file != NULL) + theme->application_stylesheet = g_object_ref (file); } break; } case PROP_THEME_STYLESHEET: { - const char *path = g_value_get_string (value); + GFile *file = g_value_get_object (value); - if (path != theme->theme_stylesheet) + if (!file_equal0 (file, theme->theme_stylesheet)) { - g_free (theme->theme_stylesheet); - theme->theme_stylesheet = g_strdup (path); + g_clear_object (&theme->theme_stylesheet); + if (file != NULL) + theme->theme_stylesheet = g_object_ref (file); } break; } case PROP_DEFAULT_STYLESHEET: { - const char *path = g_value_get_string (value); + GFile *file = g_value_get_object (value); - if (path != theme->default_stylesheet) + if (!file_equal0 (file, theme->default_stylesheet)) { - g_free (theme->default_stylesheet); - theme->default_stylesheet = g_strdup (path); + g_clear_object (&theme->default_stylesheet); + if (file != NULL) + theme->default_stylesheet = g_object_ref (file); } break; @@ -413,13 +436,13 @@ st_theme_get_property (GObject *object, switch (prop_id) { case PROP_APPLICATION_STYLESHEET: - g_value_set_string (value, theme->application_stylesheet); + g_value_set_object (value, theme->application_stylesheet); break; case PROP_THEME_STYLESHEET: - g_value_set_string (value, theme->theme_stylesheet); + g_value_set_object (value, theme->theme_stylesheet); break; case PROP_DEFAULT_STYLESHEET: - g_value_set_string (value, theme->default_stylesheet); + g_value_set_object (value, theme->default_stylesheet); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -439,9 +462,9 @@ st_theme_get_property (GObject *object, * Return value: the newly created theme object **/ StTheme * -st_theme_new (const char *application_stylesheet, - const char *theme_stylesheet, - const char *default_stylesheet) +st_theme_new (GFile *application_stylesheet, + GFile *theme_stylesheet, + GFile *default_stylesheet) { StTheme *theme = g_object_new (ST_TYPE_THEME, "application-stylesheet", application_stylesheet, @@ -852,26 +875,19 @@ add_matched_properties (StTheme *a_this, if (import_rule->sheet == NULL) { - char *filename = NULL; + GFile *file = NULL; if (import_rule->url->stryng && import_rule->url->stryng->str) { - GFile *file; - file = _st_theme_resolve_url (a_this, a_nodesheet, import_rule->url->stryng->str); - filename = g_file_get_path (file); - - g_object_unref (file); + import_rule->sheet = parse_stylesheet (file, NULL); } - if (filename) - import_rule->sheet = parse_stylesheet (filename, NULL); - if (import_rule->sheet) { - insert_stylesheet (a_this, filename, import_rule->sheet); + insert_stylesheet (a_this, file, import_rule->sheet); /* refcount of stylesheets starts off at zero, so we don't need to unref! */ } else @@ -882,8 +898,8 @@ add_matched_properties (StTheme *a_this, import_rule->sheet = (CRStyleSheet *) - 1; } - if (filename) - g_free (filename); + if (file) + g_object_unref (file); } if (import_rule->sheet != (CRStyleSheet *) - 1) @@ -1018,7 +1034,7 @@ _st_theme_resolve_url (StTheme *theme, const char *url) { char *scheme; - GFile *stylesheet, *resource; + GFile *resource; if ((scheme = g_uri_parse_scheme (url))) { @@ -1027,21 +1043,18 @@ _st_theme_resolve_url (StTheme *theme, } else if (base_stylesheet != NULL) { - const char *base_filename = NULL; - char *dirname; + GFile *base_file = NULL, *parent; - base_filename = g_hash_table_lookup (theme->filenames_by_stylesheet, base_stylesheet); + base_file = g_hash_table_lookup (theme->files_by_stylesheet, base_stylesheet); /* This is an internal function, if we get here with a bad @base_stylesheet we have a problem. */ - g_assert (base_filename); + g_assert (base_file); - dirname = g_path_get_dirname (base_filename); - stylesheet = g_file_new_for_path (dirname); - resource = g_file_resolve_relative_path (stylesheet, url); + parent = g_file_get_parent (base_file); + resource = g_file_resolve_relative_path (parent, url); - g_object_unref (stylesheet); - g_free (dirname); + g_object_unref (parent); } else { diff --git a/src/st/st-theme.h b/src/st/st-theme.h index eb0103f92..b6dee0425 100644 --- a/src/st/st-theme.h +++ b/src/st/st-theme.h @@ -47,12 +47,12 @@ typedef struct _StThemeClass StThemeClass; GType st_theme_get_type (void) G_GNUC_CONST; -StTheme *st_theme_new (const char *application_stylesheet, - const char *theme_stylesheet, - const char *default_stylesheet); +StTheme *st_theme_new (GFile *application_stylesheet, + GFile *theme_stylesheet, + GFile *default_stylesheet); -gboolean st_theme_load_stylesheet (StTheme *theme, const char *path, GError **error); -void st_theme_unload_stylesheet (StTheme *theme, const char *path); +gboolean st_theme_load_stylesheet (StTheme *theme, GFile *file, GError **error); +void st_theme_unload_stylesheet (StTheme *theme, GFile *file); GSList *st_theme_get_custom_stylesheets (StTheme *theme); G_END_DECLS diff --git a/src/st/test-theme.c b/src/st/test-theme.c index 6e7f2110d..5fa5de3cb 100644 --- a/src/st/test-theme.c +++ b/src/st/test-theme.c @@ -430,14 +430,16 @@ main (int argc, char **argv) StTheme *theme; StThemeContext *context; PangoFontDescription *font_desc; + GFile *file; gtk_init (&argc, &argv); if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; - theme = st_theme_new ("st/test-theme.css", - NULL, NULL); + file = g_file_new_for_path ("st/test-theme.css"); + theme = st_theme_new (file, NULL, NULL); + g_object_unref (file); stage = clutter_stage_new (); context = st_theme_context_get_for_stage (CLUTTER_STAGE (stage)); diff --git a/tests/testcommon/ui.js b/tests/testcommon/ui.js index 4813d76d6..b66b0cdca 100644 --- a/tests/testcommon/ui.js +++ b/tests/testcommon/ui.js @@ -1,6 +1,7 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- const Clutter = imports.gi.Clutter; +const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; const St = imports.gi.St; @@ -10,7 +11,7 @@ function init(stage) { Environment.init(); let context = St.ThemeContext.get_for_stage(stage); let stylesheetPath = GLib.getenv("GNOME_SHELL_TESTSDIR") + "/testcommon/test.css"; - let theme = new St.Theme({ application_stylesheet: stylesheetPath }); + let theme = new St.Theme({ application_stylesheet: Gio.File.new_for_path(stylesheetPath) }); context.set_theme(theme); }