Clean up code to find themes
Simplify code to find the right theme to load and loading it by moving all the loading code into a load_theme() helper function, and making meta_load_theme() use that as it searches through the directories. Look for old-version themes even when loading relative to the working in debug mode. Don't unnecessarily duplicate and then free info->theme_file and info->theme_dir. http://bugzilla.gnome.org/show_bug.cgi?id=592503
This commit is contained in:
parent
94d47dc25e
commit
0ac46316af
@ -82,8 +82,8 @@ typedef struct
|
|||||||
GSList *states;
|
GSList *states;
|
||||||
|
|
||||||
const char *theme_name; /* name of theme (directory it's in) */
|
const char *theme_name; /* name of theme (directory it's in) */
|
||||||
char *theme_file; /* theme filename */
|
const char *theme_file; /* theme filename */
|
||||||
char *theme_dir; /* dir the theme is inside */
|
const char *theme_dir; /* dir the theme is inside */
|
||||||
MetaTheme *theme; /* theme being parsed */
|
MetaTheme *theme; /* theme being parsed */
|
||||||
guint format_version; /* version of format of theme file */
|
guint format_version; /* version of format of theme file */
|
||||||
char *name; /* name of named thing being parsed */
|
char *name; /* name of named thing being parsed */
|
||||||
@ -272,9 +272,6 @@ parse_info_init (ParseInfo *info)
|
|||||||
static void
|
static void
|
||||||
parse_info_free (ParseInfo *info)
|
parse_info_free (ParseInfo *info)
|
||||||
{
|
{
|
||||||
g_free (info->theme_file);
|
|
||||||
g_free (info->theme_dir);
|
|
||||||
|
|
||||||
g_slist_free (info->states);
|
g_slist_free (info->states);
|
||||||
|
|
||||||
if (info->theme)
|
if (info->theme)
|
||||||
@ -3880,66 +3877,131 @@ text_handler (GMarkupParseContext *context,
|
|||||||
|
|
||||||
#define METACITY_THEME_FILENAME_FORMAT "metacity-theme-%d.xml"
|
#define METACITY_THEME_FILENAME_FORMAT "metacity-theme-%d.xml"
|
||||||
|
|
||||||
|
/* If the theme is not-corrupt, keep looking for alternate versions
|
||||||
|
* in other locations we might be compatible with
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
theme_error_is_fatal (GError *error)
|
||||||
|
{
|
||||||
|
return error->domain != G_FILE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaTheme *
|
||||||
|
load_theme (const char *theme_dir,
|
||||||
|
const char *theme_name,
|
||||||
|
guint major_version,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GMarkupParseContext *context;
|
||||||
|
ParseInfo info;
|
||||||
|
char *text;
|
||||||
|
gsize length;
|
||||||
|
char *theme_filename;
|
||||||
|
char *theme_file;
|
||||||
|
MetaTheme *retval;
|
||||||
|
|
||||||
|
g_return_val_if_fail (error && *error == NULL, NULL);
|
||||||
|
|
||||||
|
text = NULL;
|
||||||
|
retval = NULL;
|
||||||
|
context = NULL;
|
||||||
|
|
||||||
|
theme_filename = g_strdup_printf (METACITY_THEME_FILENAME_FORMAT, major_version);
|
||||||
|
theme_file = g_build_filename (theme_dir, theme_filename, NULL);
|
||||||
|
|
||||||
|
if (!g_file_get_contents (theme_file,
|
||||||
|
&text,
|
||||||
|
&length,
|
||||||
|
error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_THEMES, "Parsing theme file %s\n", theme_file);
|
||||||
|
|
||||||
|
parse_info_init (&info);
|
||||||
|
|
||||||
|
info.theme_name = theme_name;
|
||||||
|
info.theme_file = theme_file;
|
||||||
|
info.theme_dir = theme_dir;
|
||||||
|
|
||||||
|
info.format_version = major_version;
|
||||||
|
|
||||||
|
context = g_markup_parse_context_new (&metacity_theme_parser,
|
||||||
|
0, &info, NULL);
|
||||||
|
|
||||||
|
if (!g_markup_parse_context_parse (context,
|
||||||
|
text,
|
||||||
|
length,
|
||||||
|
error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (!g_markup_parse_context_end_parse (context, error))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
retval = info.theme;
|
||||||
|
info.theme = NULL;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (*error && !theme_error_is_fatal (*error))
|
||||||
|
{
|
||||||
|
meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n",
|
||||||
|
theme_file, (*error)->message);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (theme_filename);
|
||||||
|
g_free (theme_file);
|
||||||
|
g_free (text);
|
||||||
|
|
||||||
|
if (context)
|
||||||
|
{
|
||||||
|
g_markup_parse_context_free (context);
|
||||||
|
parse_info_free (&info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
keep_trying (GError **error)
|
||||||
|
{
|
||||||
|
if (*error && !theme_error_is_fatal (*error))
|
||||||
|
{
|
||||||
|
g_clear_error (error);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
MetaTheme*
|
MetaTheme*
|
||||||
meta_theme_load (const char *theme_name,
|
meta_theme_load (const char *theme_name,
|
||||||
GError **err)
|
GError **err)
|
||||||
{
|
{
|
||||||
GMarkupParseContext *context;
|
GError *error = NULL;
|
||||||
GError *error;
|
|
||||||
ParseInfo info;
|
|
||||||
char *text;
|
|
||||||
gsize length;
|
|
||||||
char *theme_file;
|
|
||||||
char *theme_dir;
|
char *theme_dir;
|
||||||
MetaTheme *retval;
|
MetaTheme *retval;
|
||||||
guint version;
|
|
||||||
const gchar* const* xdg_data_dirs;
|
const gchar* const* xdg_data_dirs;
|
||||||
|
int version;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
text = NULL;
|
|
||||||
length = 0;
|
|
||||||
retval = NULL;
|
retval = NULL;
|
||||||
context = NULL;
|
|
||||||
|
|
||||||
theme_dir = NULL;
|
|
||||||
theme_file = NULL;
|
|
||||||
|
|
||||||
if (meta_is_debugging ())
|
if (meta_is_debugging ())
|
||||||
{
|
{
|
||||||
gchar *theme_filename = g_strdup_printf (METACITY_THEME_FILENAME_FORMAT,
|
|
||||||
THEME_VERSION);
|
|
||||||
|
|
||||||
/* Try in themes in our source tree */
|
/* Try in themes in our source tree */
|
||||||
theme_dir = g_build_filename ("./themes", theme_name, NULL);
|
/* We try all supported major versions from current to oldest */
|
||||||
|
for (version = THEME_VERSION; (version > 0); version--)
|
||||||
theme_file = g_build_filename (theme_dir,
|
|
||||||
theme_filename,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
if (!g_file_get_contents (theme_file,
|
|
||||||
&text,
|
|
||||||
&length,
|
|
||||||
&error))
|
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n",
|
theme_dir = g_build_filename ("./themes", theme_name, NULL);
|
||||||
theme_file, error->message);
|
retval = load_theme (theme_dir, theme_name, version, &error);
|
||||||
g_error_free (error);
|
|
||||||
g_free (theme_dir);
|
g_free (theme_dir);
|
||||||
g_free (theme_file);
|
if (!keep_trying (&error))
|
||||||
theme_file = NULL;
|
goto out;
|
||||||
}
|
}
|
||||||
version = THEME_VERSION;
|
|
||||||
|
|
||||||
g_free (theme_filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We try all supported versions from current to oldest */
|
/* We try all supported major versions from current to oldest */
|
||||||
for (version = THEME_VERSION; (version > 0) && (text == NULL); version--)
|
for (version = THEME_VERSION; (version > 0); version--)
|
||||||
{
|
{
|
||||||
gchar *theme_filename = g_strdup_printf (METACITY_THEME_FILENAME_FORMAT,
|
|
||||||
version);
|
|
||||||
|
|
||||||
/* We try first in home dir, XDG_DATA_DIRS, then system dir for themes */
|
/* We try first in home dir, XDG_DATA_DIRS, then system dir for themes */
|
||||||
|
|
||||||
/* Try home dir for themes */
|
/* Try home dir for themes */
|
||||||
@ -3948,156 +4010,51 @@ meta_theme_load (const char *theme_name,
|
|||||||
theme_name,
|
theme_name,
|
||||||
THEME_SUBDIR,
|
THEME_SUBDIR,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
theme_file = g_build_filename (theme_dir,
|
|
||||||
theme_filename,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
error = NULL;
|
retval = load_theme (theme_dir, theme_name, version, &error);
|
||||||
if (!g_file_get_contents (theme_file,
|
g_free (theme_dir);
|
||||||
&text,
|
if (!keep_trying (&error))
|
||||||
&length,
|
goto out;
|
||||||
&error))
|
|
||||||
{
|
|
||||||
meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n",
|
|
||||||
theme_file, error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
g_free (theme_dir);
|
|
||||||
g_free (theme_file);
|
|
||||||
theme_file = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try each XDG_DATA_DIRS for theme */
|
/* Try each XDG_DATA_DIRS for theme */
|
||||||
xdg_data_dirs = g_get_system_data_dirs();
|
xdg_data_dirs = g_get_system_data_dirs();
|
||||||
for(i = 0; xdg_data_dirs[i] != NULL; i++)
|
for(i = 0; xdg_data_dirs[i] != NULL; i++)
|
||||||
{
|
{
|
||||||
if (text == NULL)
|
theme_dir = g_build_filename (xdg_data_dirs[i],
|
||||||
{
|
|
||||||
theme_dir = g_build_filename (xdg_data_dirs[i],
|
|
||||||
"themes",
|
|
||||||
theme_name,
|
|
||||||
THEME_SUBDIR,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
theme_file = g_build_filename (theme_dir,
|
|
||||||
theme_filename,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
if (!g_file_get_contents (theme_file,
|
|
||||||
&text,
|
|
||||||
&length,
|
|
||||||
&error))
|
|
||||||
{
|
|
||||||
meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n",
|
|
||||||
theme_file, error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
g_free (theme_dir);
|
|
||||||
g_free (theme_file);
|
|
||||||
theme_file = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look for themes in MUTTER_DATADIR */
|
|
||||||
if (text == NULL)
|
|
||||||
{
|
|
||||||
theme_dir = g_build_filename (MUTTER_DATADIR,
|
|
||||||
"themes",
|
"themes",
|
||||||
theme_name,
|
theme_name,
|
||||||
THEME_SUBDIR,
|
THEME_SUBDIR,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
theme_file = g_build_filename (theme_dir,
|
|
||||||
theme_filename,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
error = NULL;
|
retval = load_theme (theme_dir, theme_name, version, &error);
|
||||||
if (!g_file_get_contents (theme_file,
|
g_free (theme_dir);
|
||||||
&text,
|
if (!keep_trying (&error))
|
||||||
&length,
|
goto out;
|
||||||
&error))
|
|
||||||
{
|
|
||||||
meta_topic (META_DEBUG_THEMES, "Failed to read theme from file %s: %s\n",
|
|
||||||
theme_file, error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
g_free (theme_dir);
|
|
||||||
g_free (theme_file);
|
|
||||||
theme_file = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (theme_filename);
|
/* Look for themes in MUTTER_DATADIR */
|
||||||
|
theme_dir = g_build_filename (MUTTER_DATADIR,
|
||||||
|
"themes",
|
||||||
|
theme_name,
|
||||||
|
THEME_SUBDIR,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
retval = load_theme (theme_dir, theme_name, version, &error);
|
||||||
|
g_free (theme_dir);
|
||||||
|
if (!keep_trying (&error))
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text == NULL)
|
|
||||||
{
|
|
||||||
g_set_error (err, META_THEME_ERROR, META_THEME_ERROR_FAILED,
|
|
||||||
_("Failed to find a valid file for theme %s\n"),
|
|
||||||
theme_name);
|
|
||||||
|
|
||||||
return NULL; /* all fallbacks failed */
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_topic (META_DEBUG_THEMES, "Parsing theme file %s\n", theme_file);
|
|
||||||
|
|
||||||
|
|
||||||
parse_info_init (&info);
|
|
||||||
info.theme_name = theme_name;
|
|
||||||
|
|
||||||
/* pass ownership to info so we free it with the info */
|
|
||||||
info.theme_file = theme_file;
|
|
||||||
info.theme_dir = theme_dir;
|
|
||||||
|
|
||||||
info.format_version = version + 1;
|
|
||||||
|
|
||||||
context = g_markup_parse_context_new (&metacity_theme_parser,
|
|
||||||
0, &info, NULL);
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
if (!g_markup_parse_context_parse (context,
|
|
||||||
text,
|
|
||||||
length,
|
|
||||||
&error))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
if (!g_markup_parse_context_end_parse (context, &error))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
if (!error && !retval)
|
||||||
if (context)
|
g_set_error (&error, META_THEME_ERROR, META_THEME_ERROR_FAILED,
|
||||||
g_markup_parse_context_free (context);
|
_("Failed to find a valid file for theme %s\n"),
|
||||||
g_free (text);
|
theme_name);
|
||||||
|
|
||||||
if (info.theme)
|
|
||||||
info.theme->format_version = info.format_version;
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
g_propagate_error (err, error);
|
g_propagate_error (err, error);
|
||||||
}
|
}
|
||||||
else if (info.theme)
|
|
||||||
{
|
|
||||||
/* Steal theme from info */
|
|
||||||
retval = info.theme;
|
|
||||||
info.theme = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_set_error (err, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
|
||||||
_("Theme file %s did not contain a root <metacity_theme> element"),
|
|
||||||
info.theme_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_info_free (&info);
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user