[clutter] Add a configuration file for ClutterSettings
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter] Add a configuration file for ClutterSettings
- Date: Tue, 11 Oct 2011 16:56:11 +0000 (UTC)
commit f5eee5aec7a87a3c8a1f2e658231eca4b04561dd
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Tue Oct 11 14:42:31 2011 +0100
Add a configuration file for ClutterSettings
ClutterSettings should be able to load its initial state by using
configuration files in SYSCONFDIR and XDG_CONFIG_HOME. This allows
Clutter to have a system (and user) configuration on platforms that
do not have XSETTINGS bridges.
clutter/Makefile.am | 2 +
clutter/clutter-main.c | 42 +++++++++
clutter/clutter-settings-private.h | 16 ++++
clutter/clutter-settings.c | 164 +++++++++++++++++++++++++++++++++---
4 files changed, 213 insertions(+), 11 deletions(-)
---
diff --git a/clutter/Makefile.am b/clutter/Makefile.am
index d9b81a8..688617d 100644
--- a/clutter/Makefile.am
+++ b/clutter/Makefile.am
@@ -27,6 +27,7 @@ AM_CPPFLAGS = \
-DCLUTTER_LIBDIR=\""$(libdir)"\" \
-DCLUTTER_DATADIR=\""$(datadir)"\" \
-DCLUTTER_LOCALEDIR=\""$(localedir)"\" \
+ -DCLUTTER_SYSCONFDIR=\""$(sysconfdir)"\" \
-DCLUTTER_COMPILATION=1 \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DG_LOG_DOMAIN=\"Clutter\" \
@@ -240,6 +241,7 @@ source_h_priv = \
$(srcdir)/clutter-private.h \
$(srcdir)/clutter-profile.h \
$(srcdir)/clutter-script-private.h \
+ $(srcdir)/clutter-settings-private.h \
$(srcdir)/clutter-stage-manager-private.h \
$(srcdir)/clutter-stage-private.h \
$(srcdir)/clutter-timeout-interval.h \
diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c
index 4f0a6c8..8992909 100644
--- a/clutter/clutter-main.c
+++ b/clutter/clutter-main.c
@@ -99,6 +99,7 @@
#include "clutter-master-clock.h"
#include "clutter-private.h"
#include "clutter-profile.h"
+#include "clutter-settings-private.h"
#include "clutter-stage-manager.h"
#include "clutter-stage-private.h"
#include "clutter-version.h" /* For flavour define */
@@ -215,6 +216,35 @@ clutter_threads_init_default (void)
clutter_threads_unlock = clutter_threads_impl_unlock;
}
+#define N_CONF_DIRS 2
+
+static void
+clutter_config_read (void)
+{
+ ClutterSettings *settings;
+ gchar *config_path;
+
+ settings = clutter_settings_get_default ();
+
+ config_path = g_build_filename (CLUTTER_SYSCONFDIR,
+ "clutter-1.0",
+ "settings.ini",
+ NULL);
+ if (g_file_test (config_path, G_FILE_TEST_EXISTS))
+ _clutter_settings_read_from_file (settings, config_path);
+
+ g_free (config_path);
+
+ config_path = g_build_filename (g_get_user_config_dir (),
+ "clutter-1.0",
+ "settings.ini",
+ NULL);
+ if (g_file_test (config_path, G_FILE_TEST_EXISTS))
+ _clutter_settings_read_from_file (settings, config_path);
+
+ g_free (config_path);
+}
+
/**
* clutter_get_show_fps:
*
@@ -1105,6 +1135,12 @@ clutter_context_get_default_unlocked (void)
ctx->is_initialized = FALSE;
ctx->motion_events_per_actor = TRUE;
+ /* create the default settings object, and store a back pointer to
+ * the backend singleton
+ */
+ ctx->settings = clutter_settings_get_default ();
+ _clutter_settings_set_backend (ctx->settings, ctx->backend);
+
#ifdef CLUTTER_ENABLE_DEBUG
ctx->timer = g_timer_new ();
g_timer_start (ctx->timer);
@@ -1370,6 +1406,12 @@ pre_parse_hook (GOptionContext *context,
g_warning ("Locale not supported by C library.\n"
"Using the fallback 'C' locale.");
+ /* read the configuration file, if it exists; the configuration file
+ * determines the initial state of the settings, so that command line
+ * arguments can override them.
+ */
+ clutter_config_read ();
+
clutter_context = _clutter_context_get_default ();
clutter_context->id_pool = _clutter_id_pool_new (256);
diff --git a/clutter/clutter-settings-private.h b/clutter/clutter-settings-private.h
new file mode 100644
index 0000000..112f542
--- /dev/null
+++ b/clutter/clutter-settings-private.h
@@ -0,0 +1,16 @@
+#ifndef __CLUTTER_SETTINGS_PRIVATE_H__
+#define __CLUTTER_SETTINGS_PRIVATE_H__
+
+#include <clutter/clutter-backend-private.h>
+#include <clutter/clutter-settings.h>
+
+G_BEGIN_DECLS
+
+void _clutter_settings_set_backend (ClutterSettings *settings,
+ ClutterBackend *backend);
+void _clutter_settings_read_from_file (ClutterSettings *settings,
+ const gchar *file);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_SETTINGS_PRIVATE_H__ */
diff --git a/clutter/clutter-settings.c b/clutter/clutter-settings.c
index 0bc43d9..ffbc605 100644
--- a/clutter/clutter-settings.c
+++ b/clutter/clutter-settings.c
@@ -118,6 +118,9 @@ settings_update_font_options (ClutterSettings *self)
cairo_subpixel_order_t subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
cairo_font_options_t *options;
+ if (self->backend == NULL)
+ return;
+
options = cairo_font_options_create ();
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
@@ -187,7 +190,8 @@ settings_update_font_name (ClutterSettings *self)
{
CLUTTER_NOTE (BACKEND, "New font-name: %s", self->font_name);
- g_signal_emit_by_name (self->backend, "font-changed");
+ if (self->backend != NULL)
+ g_signal_emit_by_name (self->backend, "font-changed");
}
static void
@@ -195,13 +199,17 @@ settings_update_resolution (ClutterSettings *self)
{
CLUTTER_NOTE (BACKEND, "New resolution: %.2f", self->resolution);
- g_signal_emit_by_name (self->backend, "resolution-changed");
+ if (self->backend != NULL)
+ g_signal_emit_by_name (self->backend, "resolution-changed");
}
static void
settings_update_fontmap (ClutterSettings *self,
guint stamp)
{
+ if (self->backend == NULL)
+ return;
+
#ifdef HAVE_PANGO_FT2
CLUTTER_NOTE (BACKEND, "Update fontmaps (stamp: %d)", stamp);
@@ -391,7 +399,8 @@ clutter_settings_dispatch_properties_changed (GObject *gobject,
klass->dispatch_properties_changed (gobject, n_pspecs, pspecs);
/* emit settings-changed just once for multiple properties */
- g_signal_emit_by_name (self->backend, "settings-changed");
+ if (self->backend != NULL)
+ g_signal_emit_by_name (self->backend, "settings-changed");
}
static void
@@ -405,13 +414,17 @@ clutter_settings_class_init (ClutterSettingsClass *klass)
* A back pointer to the #ClutterBackend
*
* Since: 1.4
+ *
+ * Deprecated: 1.10
*/
obj_props[PROP_BACKEND] =
g_param_spec_object ("backend",
"Backend",
"A pointer to the backend",
CLUTTER_TYPE_BACKEND,
- CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+ CLUTTER_PARAM_WRITABLE |
+ G_PARAM_DEPRECATED |
+ G_PARAM_CONSTRUCT_ONLY);
/**
* ClutterSettings:double-click-time:
@@ -656,14 +669,143 @@ clutter_settings_init (ClutterSettings *self)
ClutterSettings *
clutter_settings_get_default (void)
{
- ClutterMainContext *context = _clutter_context_get_default ();
+ static ClutterSettings *settings = NULL;
+
+ if (G_UNLIKELY (settings == NULL))
+ settings = g_object_new (CLUTTER_TYPE_SETTINGS, NULL);
+
+ return settings;
+}
+
+void
+_clutter_settings_set_backend (ClutterSettings *settings,
+ ClutterBackend *backend)
+{
+ g_assert (CLUTTER_IS_SETTINGS (settings));
+ g_assert (CLUTTER_IS_BACKEND (backend));
+
+ settings->backend = backend;
+}
+
+#define SETTINGS_GROUP "Settings"
+
+void
+_clutter_settings_read_from_file (ClutterSettings *settings,
+ const gchar *file)
+{
+ GObjectClass *settings_class;
+ GObject *settings_obj;
+ GParamSpec **pspecs;
+ GKeyFile *keyfile;
+ GError *error;
+ guint n_pspecs, i;
+
+ error = NULL;
+ keyfile = g_key_file_new ();
+ g_key_file_load_from_file (keyfile, file, G_KEY_FILE_NONE, &error);
+ if (error != NULL)
+ {
+ g_critical ("Unable to read configuration from '%s': %s",
+ file,
+ error->message);
+ g_error_free (error);
+ goto out;
+ }
- if (G_LIKELY (context->settings != NULL))
- return context->settings;
+ if (!g_key_file_has_group (keyfile, SETTINGS_GROUP))
+ goto out;
+
+ settings_obj = G_OBJECT (settings);
+ settings_class = G_OBJECT_GET_CLASS (settings);
+ pspecs = g_object_class_list_properties (settings_class, &n_pspecs);
+
+ CLUTTER_NOTE (BACKEND, "Reading settings from '%s'", file);
+
+ for (i = 0; i < n_pspecs; i++)
+ {
+ GParamSpec *pspec = pspecs[i];
+ const gchar *p_name = pspec->name;
+ GType p_type = G_TYPE_FUNDAMENTAL (pspec->value_type);
+ GValue value = G_VALUE_INIT;
+ GError *key_error = NULL;
+
+ g_value_init (&value, p_type);
+
+ switch (p_type)
+ {
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ {
+ gint val;
+
+ val = g_key_file_get_integer (keyfile,
+ SETTINGS_GROUP, p_name,
+ &key_error);
+ if (p_type == G_TYPE_INT)
+ g_value_set_int (&value, val);
+ else
+ g_value_set_uint (&value, val);
+ }
+ break;
+
+ case G_TYPE_BOOLEAN:
+ {
+ gboolean val;
+
+ val = g_key_file_get_boolean (keyfile,
+ SETTINGS_GROUP, p_name,
+ &key_error);
+ g_value_set_boolean (&value, val);
+ }
+ break;
+
+ case G_TYPE_FLOAT:
+ case G_TYPE_DOUBLE:
+ {
+ gdouble val;
+
+ val = g_key_file_get_double (keyfile,
+ SETTINGS_GROUP, p_name,
+ &key_error);
+ if (p_type == G_TYPE_FLOAT)
+ g_value_set_float (&value, val);
+ else
+ g_value_set_double (&value, val);
+ }
+ break;
+
+ case G_TYPE_STRING:
+ {
+ const gchar *val;
+
+ val = g_key_file_get_string (keyfile,
+ SETTINGS_GROUP, p_name,
+ &key_error);
+ g_value_set_string (&value, val);
+ }
+ break;
+ }
+
+ if (key_error != NULL &&
+ key_error->domain != G_KEY_FILE_ERROR &&
+ key_error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND)
+ {
+ g_critical ("Unable to read the value for setting '%s' in '%s': %s",
+ p_name,
+ file,
+ key_error->message);
+ }
+
+ if (key_error == NULL)
+ g_object_set_property (settings_obj, p_name, &value);
+ else
+ g_error_free (key_error);
+
+ g_value_unset (&value);
+ }
- context->settings = g_object_new (CLUTTER_TYPE_SETTINGS,
- "backend", context->backend,
- NULL);
+ g_free (pspecs);
- return context->settings;
+out:
+ g_key_file_free (keyfile);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]