summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Spilsbury <sam.spilsbury@canonical.com>2011-07-26 17:49:55 +0800
committerSam Spilsbury <sam.spilsbury@canonical.com>2011-07-26 17:49:55 +0800
commit22472ece28d8a1a5b463359911a61758c54ddbcd (patch)
treeb17721bcc7e7471ff47c8e4aa9d8cf658e11d35a
parent4f02cdfbf265fbca4c38482f913abd90b2b4e72f (diff)
parent330c8dff0ff9bde3f4f3819a2cfedc69af982d78 (diff)
downloadcompizconfig-backend-gsettings-22472ece28d8a1a5b463359911a61758c54ddbcd.tar.gz
compizconfig-backend-gsettings-22472ece28d8a1a5b463359911a61758c54ddbcd.tar.bz2
Merge in gsettings port
-rw-r--r--CMakeLists.txt23
-rw-r--r--org.freedesktop.compizconfig.gschema.xml22
-rw-r--r--src/gconf-integration.c (renamed from src/gconf.c)1268
-rw-r--r--src/gsettings.c1251
-rw-r--r--src/gsettings.h152
5 files changed, 1501 insertions, 1215 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index caee4b8..f372d38 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,11 +1,26 @@
-project (compizconfig-backend-gconf)
+project (compizconfig-backend-gsettings)
find_package (CompizConfig REQUIRED)
include (LibCompizConfigCommon)
+include (CompizGSettings)
-compizconfig_backend (gconf PKGDEPS glib-2.0 gconf-2.0)
+set (_deps glib-2.0>=2.20.0
+ gio-2.0>=2.25.0)
-compiz_print_configure_header ("CompizConfig GConf Storage Backend")
+option (USE_GCONF "Enable legacy GNOME 2.x option integration with GConf" ON)
+
+if (USE_GCONF)
+ list (APPEND _deps gconf-2.0>=2.31.1)
+
+ add_definitions (-DUSE_GCONF)
+endif (USE_GCONF)
+
+compizconfig_backend (gsettings PKGDEPS ${_deps})
+
+compiz_install_gsettings_schema (${CMAKE_SOURCE_DIR}/org.freedesktop.compizconfig.gschema.xml
+ ${CMAKE_INSTALL_PREFIX}/share/glib-2.0/schemas)
+
+compiz_print_configure_header ("CompizConfig GSettings Storage Backend")
compiz_print_configure_footer ()
-compiz_package_generation ("CompizConfig GConf Storage Backend")
+compiz_package_generation ("CompizConfig GSettings Storage Backend")
diff --git a/org.freedesktop.compizconfig.gschema.xml b/org.freedesktop.compizconfig.gschema.xml
new file mode 100644
index 0000000..ac3701f
--- /dev/null
+++ b/org.freedesktop.compizconfig.gschema.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<schemalist>
+ <schema id="org.freedesktop.compizconfig" path="/org/freedesktop/compizconfig/" gettext-domain="compiz">
+ <key type="s" name="current-profile">
+ <default>'Default'</default>
+ <summary>Current Profile</summary>
+ <description>Describes the current profile</description>
+ </key>
+ <key type="as" name="existing-profiles">
+ <default>['Default']</default>
+ <summary>Existing Profiles</summary>
+ <description>Profiles available for the GSettings backend to use</description>
+ </key>
+ </schema>
+ <schema id="org.freedesktop.compizconfig.profile" gettext-domain="compiz">
+ <key type="as" name="plugins-with-set-keys">
+ <default>[]</default>
+ <summary>Plugins with set keys</summary>
+ <description>Plugins which have set keys</description>
+ </key>
+ </schema>
+</schemalist>
diff --git a/src/gconf.c b/src/gconf-integration.c
index 342e3b1..067e28d 100644
--- a/src/gconf.c
+++ b/src/gconf-integration.c
@@ -1,8 +1,12 @@
/**
*
- * GConf libccs backend
+ * GSettings libccs backend
*
- * gconf.c
+ * gconf-integration.c
+ *
+ * Copyright (c) 2011 Canonical Ltd
+ *
+ * Based on the original compizconfig-backend-gconf
*
* Copyright (c) 2007 Danny Baumann <maniac@opencompositing.org>
*
@@ -22,95 +26,17 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
+ * Authored By:
+ * Sam Spilsbury <sam.spilsbury@canonical.com>
+ *
**/
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <malloc.h>
-#include <string.h>
-#include <dirent.h>
-
-#include <ccs.h>
-#include <ccs-backend.h>
-
-#include <X11/X.h>
-#include <X11/Xlib.h>
-
-#include <gconf/gconf.h>
-#include <gconf/gconf-client.h>
-#include <gconf/gconf-value.h>
-
-#define CompAltMask (1 << 16)
-#define CompMetaMask (1 << 17)
-#define CompSuperMask (1 << 18)
-#define CompHyperMask (1 << 19)
-#define CompModeSwitchMask (1 << 20)
-#define CompNumLockMask (1 << 21)
-#define CompScrollLockMask (1 << 22)
-
-#define METACITY "/apps/metacity"
-#define COMPIZ "/apps/compiz-1"
-#define COMPIZCONFIG "/apps/compizconfig-1"
-#define PROFILEPATH COMPIZCONFIG "/profiles"
-#define DEFAULTPROF "Default"
-#define CORE_NAME "core"
-
-#define BUFSIZE 512
-
-#define KEYNAME(sn) char keyName[BUFSIZE]; \
- snprintf (keyName, BUFSIZE, "screen%i", sn);
-
-#define PATHNAME char pathName[BUFSIZE]; \
- if (!setting->parent->name || \
- strcmp (setting->parent->name, "core") == 0) \
- snprintf (pathName, BUFSIZE, \
- "%s/general/%s/options/%s", COMPIZ, \
- keyName, setting->name); \
- else \
- snprintf(pathName, BUFSIZE, \
- "%s/plugins/%s/%s/options/%s", COMPIZ, \
- setting->parent->name, keyName, setting->name);
-
-static const char* watchedGnomeDirectories[] = {
- METACITY,
- "/desktop/gnome/applications/terminal",
- "/apps/panel/applets/window_list/prefs"
-};
-#define NUM_WATCHED_DIRS 3
-
-static GConfClient *client = NULL;
-static GConfEngine *conf = NULL;
-static guint compizNotifyId;
-static guint gnomeNotifyIds[NUM_WATCHED_DIRS];
-static char *currentProfile = NULL;
-
-/* some forward declarations */
-static Bool readInit (CCSContext * context);
-static void readSetting (CCSContext * context, CCSSetting * setting);
-static Bool readOption (CCSSetting * setting);
-static Bool writeInit (CCSContext * context);
-static void writeIntegratedOption (CCSContext *context, CCSSetting *setting,
- int index);
-
-typedef enum {
- OptionInt,
- OptionBool,
- OptionKey,
- OptionString,
- OptionSpecial,
-} SpecialOptionType;
-
-typedef struct _SpecialOption {
- const char* settingName;
- const char* pluginName;
- Bool screen;
- const char* gnomeName;
- SpecialOptionType type;
-} SpecialOption;
-
-const SpecialOption specialOptions[] = {
+#include "gsettings.h"
+#ifdef USE_GCONF
+GConfClient *client = NULL;
+guint gnomeGConfNotifyIds[NUM_WATCHED_DIRS];
+
+const SpecialOptionGConf specialOptions[] = {
{"run_key", "gnomecompat", FALSE,
METACITY "/global_keybindings/panel_run_dialog", OptionKey},
{"main_menu_key", "gnomecompat", FALSE,
@@ -376,7 +302,13 @@ const SpecialOption specialOptions[] = {
METACITY "/general/num_workspaces", OptionInt},*/
};
-#define N_SOPTIONS (sizeof (specialOptions) / sizeof (struct _SpecialOption))
+static const char* watchedGConfGnomeDirectories[] = {
+ METACITY,
+ "/desktop/gnome/applications/terminal",
+ "/apps/panel/applets/window_list/prefs"
+};
+
+#define N_SOPTIONS (sizeof (specialOptions) / sizeof (struct _SpecialOptionGConf))
static CCSSetting *
findDisplaySettingForPlugin (CCSContext *context,
@@ -397,15 +329,15 @@ findDisplaySettingForPlugin (CCSContext *context,
return s;
}
-static Bool
-isIntegratedOption (CCSSetting *setting,
- int *index)
+Bool
+isGConfIntegratedOption (CCSSetting *setting,
+ int *index)
{
unsigned int i;
for (i = 0; i < N_SOPTIONS; i++)
{
- const SpecialOption *opt = &specialOptions[i];
+ const SpecialOptionGConf *opt = &specialOptions[i];
if (strcmp (setting->name, opt->settingName) != 0)
continue;
@@ -432,80 +364,11 @@ isIntegratedOption (CCSSetting *setting,
return FALSE;
}
-static void
-valueChanged (GConfClient *client,
- guint cnxn_id,
- GConfEntry *entry,
- gpointer user_data)
-{
- CCSContext *context = (CCSContext *)user_data;
- char *keyName = (char*) gconf_entry_get_key (entry);
- char *pluginName;
- char *token;
- int index;
- Bool isScreen;
- unsigned int screenNum;
- CCSPlugin *plugin;
- CCSSetting *setting;
-
- keyName += strlen (COMPIZ) + 1;
-
- token = strsep (&keyName, "/"); /* plugin */
- if (!token)
- return;
-
- if (strcmp (token, "general") == 0)
- {
- pluginName = "core";
- }
- else
- {
- token = strsep (&keyName, "/");
- if (!token)
- return;
- pluginName = token;
- }
-
- plugin = ccsFindPlugin (context, pluginName);
- if (!plugin)
- return;
-
- token = strsep (&keyName, "/");
- if (!token)
- return;
-
- isScreen = TRUE;
- sscanf (token, "screen%d", &screenNum);
-
- token = strsep (&keyName, "/"); /* 'options' */
- if (!token)
- return;
-
- token = strsep (&keyName, "/");
- if (!token)
- return;
-
- setting = ccsFindSetting (plugin, token);
- if (!setting)
- return;
-
- readInit (context);
- if (!readOption (setting))
- ccsResetToDefault (setting);
-
- if (ccsGetIntegrationEnabled (context) &&
- isIntegratedOption (setting, &index))
- {
- writeInit (context);
- writeIntegratedOption (context, setting, index);
- }
-}
-
-static void
-gnomeValueChanged (GConfClient *client,
- guint cnxn_id,
- GConfEntry *entry,
- gpointer user_data)
+void
+gnomeGConfValueChanged (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer user_data)
{
CCSContext *context = (CCSContext *)user_data;
char *keyName = (char*) gconf_entry_get_key (entry);
@@ -565,17 +428,13 @@ gnomeValueChanged (GConfClient *client,
{
CCSPlugin *plugin = NULL;
CCSSetting *setting;
- SpecialOption *opt = (SpecialOption *) &specialOptions[num];
+ SpecialOptionGConf *opt = (SpecialOptionGConf *) &specialOptions[num];
plugin = ccsFindPlugin (context, (char*) opt->pluginName);
if (plugin)
{
for (i = 0; i < 1; i++)
{
- unsigned int screen;
-
- screen = 0;
-
setting = ccsFindSetting (plugin, (char*) opt->settingName);
if (setting)
@@ -596,324 +455,44 @@ gnomeValueChanged (GConfClient *client,
}
}
-static void
-initClient (CCSContext *context)
+void
+initGConfClient (CCSContext *context)
{
int i;
- client = gconf_client_get_for_engine (conf);
-
- compizNotifyId = gconf_client_notify_add (client, COMPIZ, valueChanged,
- context, NULL, NULL);
- gconf_client_add_dir (client, COMPIZ, GCONF_CLIENT_PRELOAD_NONE, NULL);
+ client = gconf_client_get_default ();
for (i = 0; i < NUM_WATCHED_DIRS; i++)
{
- gnomeNotifyIds[i] = gconf_client_notify_add (client,
- watchedGnomeDirectories[i],
- gnomeValueChanged, context,
+ gnomeGConfNotifyIds[i] = gconf_client_notify_add (client,
+ watchedGConfGnomeDirectories[i],
+ gnomeGConfValueChanged, context,
NULL, NULL);
- gconf_client_add_dir (client, watchedGnomeDirectories[i],
+ gconf_client_add_dir (client, watchedGConfGnomeDirectories[i],
GCONF_CLIENT_PRELOAD_NONE, NULL);
}
}
-static void
-finiClient (void)
+void
+finiGConfClient (void)
{
int i;
- if (compizNotifyId)
- {
- gconf_client_notify_remove (client, compizNotifyId);
- compizNotifyId = 0;
- }
- gconf_client_remove_dir (client, COMPIZ, NULL);
-
for (i = 0; i < NUM_WATCHED_DIRS; i++)
{
- if (gnomeNotifyIds[i])
+ if (gnomeGConfNotifyIds[i])
{
- gconf_client_notify_remove (client, gnomeNotifyIds[0]);
- gnomeNotifyIds[i] = 0;
+ gconf_client_notify_remove (client, gnomeGConfNotifyIds[0]);
+ gnomeGConfNotifyIds[i] = 0;
}
- gconf_client_remove_dir (client, watchedGnomeDirectories[i], NULL);
+ gconf_client_remove_dir (client, watchedGConfGnomeDirectories[i], NULL);
}
-
gconf_client_suggest_sync (client, NULL);
g_object_unref (client);
client = NULL;
}
-static void
-copyGconfValues (GConfEngine *conf,
- const gchar *from,
- const gchar *to,
- Bool associate,
- const gchar *schemaPath)
-{
- GSList *values, *tmp;
- GError *err = NULL;
-
- values = gconf_engine_all_entries (conf, from, &err);
- tmp = values;
-
- while (tmp)
- {
- GConfEntry *entry = tmp->data;
- GConfValue *value;
- const char *key = gconf_entry_get_key (entry);
- char *name, *newKey, *newSchema = NULL;
-
- name = strrchr (key, '/');
- if (!name)
- continue;
-
- if (to)
- {
- asprintf (&newKey, "%s/%s", to, name + 1);
-
- if (associate && schemaPath)
- asprintf (&newSchema, "%s/%s", schemaPath, name + 1);
-
- if (newKey && newSchema)
- gconf_engine_associate_schema (conf, newKey, newSchema, NULL);
-
- if (newKey)
- {
- value = gconf_engine_get_without_default (conf, key, NULL);
- if (value)
- {
- gconf_engine_set (conf, newKey, value, NULL);
- gconf_value_free (value);
- }
- }
-
- if (newSchema)
- free (newSchema);
- if (newKey)
- free (newKey);
- }
- else
- {
- if (associate)
- gconf_engine_associate_schema (conf, key, NULL, NULL);
- gconf_engine_unset (conf, key, NULL);
- }
-
- gconf_entry_unref (entry);
- tmp = g_slist_next (tmp);
- }
-
- if (values)
- g_slist_free (values);
-}
-
-static void
-copyGconfRecursively (GConfEngine *conf,
- GSList *subdirs,
- const gchar *to,
- Bool associate,
- const gchar *schemaPath)
-{
- GSList* tmp;
-
- tmp = subdirs;
-
- while (tmp)
- {
- gchar *path = tmp->data;
- char *newKey, *newSchema = NULL, *name;
-
- name = strrchr (path, '/');
- if (name)
- {
- if (to)
- asprintf (&newKey, "%s/%s", to, name + 1);
- else
- newKey = NULL;
-
- if (associate && schemaPath)
- asprintf (&newSchema, "%s/%s", schemaPath, name + 1);
-
- copyGconfValues (conf, path, newKey, associate, newSchema);
- copyGconfRecursively (conf,
- gconf_engine_all_dirs (conf, path, NULL),
- newKey, associate, newSchema);
-
- if (newSchema)
- free (newSchema);
-
- if (newKey)
- free (newKey);
-
- if (!to)
- gconf_engine_remove_dir (conf, path, NULL);
- }
-
- g_free (path);
- tmp = g_slist_next (tmp);
- }
-
- if (subdirs)
- g_slist_free (subdirs);
-}
-
-static void
-copyGconfTree (CCSContext *context,
- const gchar *from,
- const gchar *to,
- Bool associate,
- const gchar *schemaPath)
-{
- GSList* subdirs;
-
- /* we aren't allowed to have an open GConfClient object while
- using GConfEngine, so shut it down and open it again afterwards */
- finiClient ();
-
- subdirs = gconf_engine_all_dirs (conf, from, NULL);
- gconf_engine_suggest_sync (conf, NULL);
-
- copyGconfRecursively (conf, subdirs, to, associate, schemaPath);
-
- gconf_engine_suggest_sync (conf, NULL);
-
- initClient (context);
-}
-
-static Bool
-readListValue (CCSSetting *setting,
- GConfValue *gconfValue)
-{
- GConfValueType valueType;
- unsigned int nItems, i = 0;
- CCSSettingValueList list = NULL;
- GSList *valueList = NULL;
-
- switch (setting->info.forList.listType)
- {
- case TypeString:
- case TypeMatch:
- case TypeColor:
- valueType = GCONF_VALUE_STRING;
- break;
- case TypeBool:
- valueType = GCONF_VALUE_BOOL;
- break;
- case TypeInt:
- valueType = GCONF_VALUE_INT;
- break;
- case TypeFloat:
- valueType = GCONF_VALUE_FLOAT;
- break;
- default:
- valueType = GCONF_VALUE_INVALID;
- break;
- }
-
- if (valueType == GCONF_VALUE_INVALID)
- return FALSE;
-
- if (valueType != gconf_value_get_list_type (gconfValue))
- return FALSE;
-
- valueList = gconf_value_get_list (gconfValue);
- if (!valueList)
- {
- ccsSetList (setting, NULL);
- return TRUE;
- }
-
- nItems = g_slist_length (valueList);
-
- switch (setting->info.forList.listType)
- {
- case TypeBool:
- {
- Bool *array = malloc (nItems * sizeof (Bool));
- if (!array)
- break;
-
- for (; valueList; valueList = valueList->next, i++)
- array[i] =
- gconf_value_get_bool (valueList->data) ? TRUE : FALSE;
- list = ccsGetValueListFromBoolArray (array, nItems, setting);
- free (array);
- }
- break;
- case TypeInt:
- {
- int *array = malloc (nItems * sizeof (int));
- if (!array)
- break;
-
- for (; valueList; valueList = valueList->next, i++)
- array[i] = gconf_value_get_int (valueList->data);
- list = ccsGetValueListFromIntArray (array, nItems, setting);
- free (array);
- }
- break;
- case TypeFloat:
- {
- float *array = malloc (nItems * sizeof (float));
- if (!array)
- break;
-
- for (; valueList; valueList = valueList->next, i++)
- array[i] = gconf_value_get_float (valueList->data);
- list = ccsGetValueListFromFloatArray (array, nItems, setting);
- free (array);
- }
- break;
- case TypeString:
- case TypeMatch:
- {
- char **array = malloc (nItems * sizeof (char*));
- if (!array)
- break;
-
- for (; valueList; valueList = valueList->next, i++)
- array[i] = strdup (gconf_value_get_string (valueList->data));
- list = ccsGetValueListFromStringArray (array, nItems, setting);
- for (i = 0; i < nItems; i++)
- if (array[i])
- free (array[i]);
- free (array);
- }
- break;
- case TypeColor:
- {
- CCSSettingColorValue *array;
- array = malloc (nItems * sizeof (CCSSettingColorValue));
- if (!array)
- break;
-
- for (; valueList; valueList = valueList->next, i++)
- {
- memset (&array[i], 0, sizeof (CCSSettingColorValue));
- ccsStringToColor (gconf_value_get_string (valueList->data),
- &array[i]);
- }
- list = ccsGetValueListFromColorArray (array, nItems, setting);
- free (array);
- }
- break;
- default:
- break;
- }
-
- if (list)
- {
- ccsSetList (setting, list);
- ccsSettingValueListFree (list, TRUE);
- return TRUE;
- }
-
- return FALSE;
-}
-
static unsigned int
getGnomeMouseButtonModifier(void)
{
@@ -957,15 +536,16 @@ getButtonBindingForSetting (CCSContext *context,
return s->value->value.asButton.button;
}
-
-static Bool
-readIntegratedOption (CCSContext *context,
- CCSSetting *setting,
- int index)
+Bool
+readGConfIntegratedOption (CCSContext *context,
+ CCSSetting *setting,
+ int index)
{
GConfValue *gconfValue;
GError *err = NULL;
Bool ret = FALSE;
+
+ ret = readOption (setting);
gconfValue = gconf_client_get (client,
specialOptions[index].gnomeName,
@@ -1124,304 +704,6 @@ readIntegratedOption (CCSContext *context,
}
static Bool
-readOption (CCSSetting * setting)
-{
- GConfValue *gconfValue = NULL;
- GError *err = NULL;
- Bool ret = FALSE;
- Bool valid = TRUE;
-
- KEYNAME(setting->parent->context->screenNum);
- PATHNAME;
-
- /* first check if the key is set */
- gconfValue = gconf_client_get_without_default (client, pathName, &err);
- if (err)
- {
- g_error_free (err);
- return FALSE;
- }
- if (!gconfValue)
- /* value is not set */
- return FALSE;
-
- /* setting type sanity check */
- switch (setting->type)
- {
- case TypeString:
- case TypeMatch:
- case TypeColor:
- case TypeKey:
- case TypeButton:
- case TypeEdge:
- valid = (gconfValue->type == GCONF_VALUE_STRING);
- break;
- case TypeInt:
- valid = (gconfValue->type == GCONF_VALUE_INT);
- break;
- case TypeBool:
- case TypeBell:
- valid = (gconfValue->type == GCONF_VALUE_BOOL);
- break;
- case TypeFloat:
- valid = (gconfValue->type == GCONF_VALUE_FLOAT);
- break;
- case TypeList:
- valid = (gconfValue->type == GCONF_VALUE_LIST);
- break;
- default:
- break;
- }
- if (!valid)
- {
- printf ("GConf backend: There is an unsupported value at path %s. "
- "Settings from this path won't be read. Try to remove "
- "that value so that operation can continue properly.\n",
- pathName);
- return FALSE;
- }
-
- switch (setting->type)
- {
- case TypeString:
- {
- const char *value;
- value = gconf_value_get_string (gconfValue);
- if (value)
- {
- ccsSetString (setting, value);
- ret = TRUE;
- }
- }
- break;
- case TypeMatch:
- {
- const char * value;
- value = gconf_value_get_string (gconfValue);
- if (value)
- {
- ccsSetMatch (setting, value);
- ret = TRUE;
- }
- }
- break;
- case TypeInt:
- {
- int value;
- value = gconf_value_get_int (gconfValue);
-
- ccsSetInt (setting, value);
- ret = TRUE;
- }
- break;
- case TypeBool:
- {
- gboolean value;
- value = gconf_value_get_bool (gconfValue);
-
- ccsSetBool (setting, value ? TRUE : FALSE);
- ret = TRUE;
- }
- break;
- case TypeFloat:
- {
- double value;
- value = gconf_value_get_float (gconfValue);
-
- ccsSetFloat (setting, (float)value);
- ret = TRUE;
- }
- break;
- case TypeColor:
- {
- const char *value;
- CCSSettingColorValue color;
- value = gconf_value_get_string (gconfValue);
-
- if (value && ccsStringToColor (value, &color))
- {
- ccsSetColor (setting, color);
- ret = TRUE;
- }
- }
- break;
- case TypeKey:
- {
- const char *value;
- CCSSettingKeyValue key;
- value = gconf_value_get_string (gconfValue);
-
- if (value && ccsStringToKeyBinding (value, &key))
- {
- ccsSetKey (setting, key);
- ret = TRUE;
- }
- }
- break;
- case TypeButton:
- {
- const char *value;
- CCSSettingButtonValue button;
- value = gconf_value_get_string (gconfValue);
-
- if (value && ccsStringToButtonBinding (value, &button))
- {
- ccsSetButton (setting, button);
- ret = TRUE;
- }
- }
- break;
- case TypeEdge:
- {
- const char *value;
- value = gconf_value_get_string (gconfValue);
-
- if (value)
- {
- unsigned int edges;
- edges = ccsStringToEdges (value);
- ccsSetEdge (setting, edges);
- ret = TRUE;
- }
- }
- break;
- case TypeBell:
- {
- gboolean value;
- value = gconf_value_get_bool (gconfValue);
-
- ccsSetBell (setting, value ? TRUE : FALSE);
- ret = TRUE;
- }
- break;
- case TypeList:
- ret = readListValue (setting, gconfValue);
- break;
- default:
- printf("GConf backend: attempt to read unsupported setting type %d from path %s!\n",
- setting->type, pathName);
- break;
- }
-
- if (gconfValue)
- gconf_value_free (gconfValue);
-
- return ret;
-}
-
-static void
-writeListValue (CCSSetting *setting,
- char *pathName)
-{
- GSList *valueList = NULL;
- GConfValueType valueType;
- Bool freeItems = FALSE;
- CCSSettingValueList list;
- gpointer data;
-
- if (!ccsGetList (setting, &list))
- return;
-
- switch (setting->info.forList.listType)
- {
- case TypeBool:
- {
- while (list)
- {
- data = GINT_TO_POINTER (list->data->value.asBool);
- valueList = g_slist_append (valueList, data);
- list = list->next;
- }
- valueType = GCONF_VALUE_BOOL;
- }
- break;
- case TypeInt:
- {
- while (list)
- {
- data = GINT_TO_POINTER (list->data->value.asInt);
- valueList = g_slist_append(valueList, data);
- list = list->next;
- }
- valueType = GCONF_VALUE_INT;
- }
- break;
- case TypeFloat:
- {
- gdouble *item;
- while (list)
- {
- item = malloc (sizeof (gdouble));
- if (item)
- {
- *item = list->data->value.asFloat;
- valueList = g_slist_append (valueList, item);
- }
- list = list->next;
- }
- freeItems = TRUE;
- valueType = GCONF_VALUE_FLOAT;
- }
- break;
- case TypeString:
- {
- while (list)
- {
- valueList = g_slist_append(valueList,
- list->data->value.asString);
- list = list->next;
- }
- valueType = GCONF_VALUE_STRING;
- }
- break;
- case TypeMatch:
- {
- while (list)
- {
- valueList = g_slist_append(valueList,
- list->data->value.asMatch);
- list = list->next;
- }
- valueType = GCONF_VALUE_STRING;
- }
- break;
- case TypeColor:
- {
- char *item;
- while (list)
- {
- item = ccsColorToString (&list->data->value.asColor);
- valueList = g_slist_append (valueList, item);
- list = list->next;
- }
- freeItems = TRUE;
- valueType = GCONF_VALUE_STRING;
- }
- break;
- default:
- printf("GConf backend: attempt to write unsupported list type %d at path %s!\n",
- setting->info.forList.listType, pathName);
- valueType = GCONF_VALUE_INVALID;
- break;
- }
-
- if (valueType != GCONF_VALUE_INVALID)
- {
- gconf_client_set_list (client, pathName, valueType, valueList, NULL);
-
- if (freeItems)
- {
- GSList *tmpList = valueList;
- for (; tmpList; tmpList = tmpList->next)
- if (tmpList->data)
- free (tmpList->data);
- }
- }
- if (valueList)
- g_slist_free (valueList);
-}
-
-static Bool
setGnomeMouseButtonModifier (unsigned int modMask)
{
char *modifiers, *currentValue;
@@ -1482,14 +764,14 @@ setButtonBindingForSetting (CCSContext *context,
}
}
-static void
-writeIntegratedOption (CCSContext *context,
- CCSSetting *setting,
- int index)
+void
+writeGConfIntegratedOption (CCSContext *context,
+ CCSSetting *setting,
+ int index)
{
GError *err = NULL;
const char *optionName = specialOptions[index].gnomeName;
-
+
switch (specialOptions[index].type)
{
case OptionInt:
@@ -1669,440 +951,4 @@ writeIntegratedOption (CCSContext *context,
if (err)
g_error_free (err);
}
-
-static void
-resetOptionToDefault (CCSSetting * setting)
-{
- KEYNAME (setting->parent->context->screenNum);
- PATHNAME;
-
- gconf_client_recursive_unset (client, pathName, 0, NULL);
- gconf_client_suggest_sync (client, NULL);
-}
-
-static void
-writeOption (CCSSetting * setting)
-{
- KEYNAME (setting->parent->context->screenNum);
- PATHNAME;
-
- switch (setting->type)
- {
- case TypeString:
- {
- char *value;
- if (ccsGetString (setting, &value))
- gconf_client_set_string (client, pathName, value, NULL);
- }
- break;
- case TypeMatch:
- {
- char *value;
- if (ccsGetMatch (setting, &value))
- gconf_client_set_string (client, pathName, value, NULL);
- }
- case TypeFloat:
- {
- float value;
- if (ccsGetFloat (setting, &value))
- gconf_client_set_float (client, pathName, value, NULL);
- }
- break;
- case TypeInt:
- {
- int value;
- if (ccsGetInt (setting, &value))
- gconf_client_set_int (client, pathName, value, NULL);
- }
- break;
- case TypeBool:
- {
- Bool value;
- if (ccsGetBool (setting, &value))
- gconf_client_set_bool (client, pathName, value, NULL);
- }
- break;
- case TypeColor:
- {
- CCSSettingColorValue value;
- char *colString;
-
- if (!ccsGetColor (setting, &value))
- break;
-
- colString = ccsColorToString (&value);
- if (!colString)
- break;
-
- gconf_client_set_string (client, pathName, colString, NULL);
- free (colString);
- }
- break;
- case TypeKey:
- {
- CCSSettingKeyValue key;
- char *keyString;
-
- if (!ccsGetKey (setting, &key))
- break;
-
- keyString = ccsKeyBindingToString (&key);
- if (!keyString)
- break;
-
- gconf_client_set_string (client, pathName, keyString, NULL);
- free (keyString);
- }
- break;
- case TypeButton:
- {
- CCSSettingButtonValue button;
- char *buttonString;
-
- if (!ccsGetButton (setting, &button))
- break;
-
- buttonString = ccsButtonBindingToString (&button);
- if (!buttonString)
- break;
-
- gconf_client_set_string (client, pathName, buttonString, NULL);
- free (buttonString);
- }
- break;
- case TypeEdge:
- {
- unsigned int edges;
- char *edgeString;
-
- if (!ccsGetEdge (setting, &edges))
- break;
-
- edgeString = ccsEdgesToString (edges);
- if (!edgeString)
- break;
-
- gconf_client_set_string (client, pathName, edgeString, NULL);
- free (edgeString);
- }
- break;
- case TypeBell:
- {
- Bool value;
- if (ccsGetBell (setting, &value))
- gconf_client_set_bool (client, pathName, value, NULL);
- }
- break;
- case TypeList:
- writeListValue (setting, pathName);
- break;
- default:
- printf("GConf backend: attempt to write unsupported setting type %d\n",
- setting->type);
- break;
- }
-}
-
-static void
-updateCurrentProfileName (char *profile)
-{
- GConfSchema *schema;
- GConfValue *value;
-
- schema = gconf_schema_new ();
- if (!schema)
- return;
-
- value = gconf_value_new (GCONF_VALUE_STRING);
- if (!value)
- {
- gconf_schema_free (schema);
- return;
- }
-
- gconf_schema_set_type (schema, GCONF_VALUE_STRING);
- gconf_schema_set_locale (schema, "C");
- gconf_schema_set_short_desc (schema, "Current profile");
- gconf_schema_set_long_desc (schema, "Current profile of gconf backend");
- gconf_schema_set_owner (schema, "compizconfig-1");
- gconf_value_set_string (value, profile);
- gconf_schema_set_default_value (schema, value);
-
- gconf_client_set_schema (client, COMPIZCONFIG "/current_profile",
- schema, NULL);
-
- gconf_schema_free (schema);
- gconf_value_free (value);
-}
-
-static char*
-getCurrentProfileName (void)
-{
- GConfSchema *schema = NULL;
-
- schema = gconf_client_get_schema (client,
- COMPIZCONFIG "/current_profile", NULL);
-
- if (schema)
- {
- GConfValue *value;
- char *ret = NULL;
-
- value = gconf_schema_get_default_value (schema);
- if (value)
- ret = strdup (gconf_value_get_string (value));
- gconf_schema_free (schema);
-
- return ret;
- }
-
- return strdup (DEFAULTPROF);
-}
-
-static Bool
-checkProfile (CCSContext *context)
-{
- char *profile, *lastProfile;
-
- lastProfile = currentProfile;
-
- profile = ccsGetProfile (context);
- if (!profile || !strlen (profile))
- currentProfile = strdup (DEFAULTPROF);
- else
- currentProfile = strdup (profile);
-
- if (!lastProfile || strcmp (lastProfile, currentProfile) != 0)
- {
- char *pathName;
-
- if (lastProfile)
- {
- /* copy /apps/compiz-1 tree to profile path */
- asprintf (&pathName, "%s/%s", PROFILEPATH, lastProfile);
- if (pathName)
- {
- copyGconfTree (context, COMPIZ, pathName,
- TRUE, "/schemas" COMPIZ);
- free (pathName);
- }
- }
-
- /* reset /apps/compiz-1 tree */
- gconf_client_recursive_unset (client, COMPIZ, 0, NULL);
-
- /* copy new profile tree to /apps/compiz-1 */
- asprintf (&pathName, "%s/%s", PROFILEPATH, currentProfile);
- if (pathName)
- {
- copyGconfTree (context, pathName, COMPIZ, FALSE, NULL);
-
- /* delete the new profile tree in /apps/compizconfig-1
- to avoid user modification in the wrong tree */
- copyGconfTree (context, pathName, NULL, TRUE, NULL);
- free (pathName);
- }
-
- /* update current profile name */
- updateCurrentProfileName (currentProfile);
- }
-
- free (lastProfile);
-
- return TRUE;
-}
-
-static void
-processEvents (unsigned int flags)
-{
- if (!(flags & ProcessEventsNoGlibMainLoopMask))
- {
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
- }
-}
-
-static Bool
-initBackend (CCSContext * context)
-{
- g_type_init ();
-
- conf = gconf_engine_get_default ();
- initClient (context);
-
- currentProfile = getCurrentProfileName ();
-
- return TRUE;
-}
-
-static Bool
-finiBackend (CCSContext * context)
-{
- processEvents (0);
-
- gconf_client_clear_cache (client);
- finiClient ();
-
- if (currentProfile)
- {
- free (currentProfile);
- currentProfile = NULL;
- }
-
- gconf_engine_unref (conf);
- conf = NULL;
-
- processEvents (0);
- return TRUE;
-}
-
-static Bool
-readInit (CCSContext * context)
-{
- return checkProfile (context);
-}
-
-static void
-readSetting (CCSContext *context,
- CCSSetting *setting)
-{
- Bool status;
- int index;
-
- if (ccsGetIntegrationEnabled (context) &&
- isIntegratedOption (setting, &index))
- {
- status = readIntegratedOption (context, setting, index);
- }
- else
- status = readOption (setting);
-
- if (!status)
- ccsResetToDefault (setting);
-}
-
-static Bool
-writeInit (CCSContext * context)
-{
- return checkProfile (context);
-}
-
-static void
-writeSetting (CCSContext *context,
- CCSSetting *setting)
-{
- int index;
-
- if (ccsGetIntegrationEnabled (context) &&
- isIntegratedOption (setting, &index))
- {
- writeIntegratedOption (context, setting, index);
- }
- else if (setting->isDefault)
- {
- resetOptionToDefault (setting);
- }
- else
- writeOption (setting);
-
-}
-
-static Bool
-getSettingIsIntegrated (CCSSetting * setting)
-{
- if (!ccsGetIntegrationEnabled (setting->parent->context))
- return FALSE;
-
- if (!isIntegratedOption (setting, NULL))
- return FALSE;
-
- return TRUE;
-}
-
-static Bool
-getSettingIsReadOnly (CCSSetting * setting)
-{
- /* FIXME */
- return FALSE;
-}
-
-static CCSStringList
-getExistingProfiles (CCSContext *context)
-{
- GSList *data, *tmp;
- CCSStringList ret = NULL;
- char *name;
-
- gconf_client_suggest_sync (client, NULL);
- data = gconf_client_all_dirs (client, PROFILEPATH, NULL);
-
- for (tmp = data; tmp; tmp = g_slist_next (tmp))
- {
- name = strrchr (tmp->data, '/');
- if (name && (strcmp (name + 1, DEFAULTPROF) != 0))
- ret = ccsStringListAppend (ret, strdup (name + 1));
-
- g_free (tmp->data);
- }
-
- g_slist_free (data);
-
- name = getCurrentProfileName ();
- if (strcmp (name, DEFAULTPROF) != 0)
- ret = ccsStringListAppend (ret, name);
- else
- free (name);
-
- return ret;
-}
-
-static Bool
-deleteProfile (CCSContext *context,
- char *profile)
-{
- char path[BUFSIZE];
- gboolean status = FALSE;
-
- checkProfile (context);
-
- snprintf (path, BUFSIZE, "%s/%s", PROFILEPATH, profile);
-
- if (gconf_client_dir_exists (client, path, NULL))
- {
- status =
- gconf_client_recursive_unset (client, path,
- GCONF_UNSET_INCLUDING_SCHEMA_NAMES,
- NULL);
- gconf_client_suggest_sync (client, NULL);
- }
-
- return status;
-}
-
-static CCSBackendVTable gconfVTable = {
- "gconf",
- "GConf Configuration Backend",
- "GConf Configuration Backend for libccs",
- TRUE,
- TRUE,
- processEvents,
- initBackend,
- finiBackend,
- readInit,
- readSetting,
- 0,
- writeInit,
- writeSetting,
- 0,
- getSettingIsIntegrated,
- getSettingIsReadOnly,
- getExistingProfiles,
- deleteProfile
-};
-
-CCSBackendVTable *
-getBackendInfo (void)
-{
- return &gconfVTable;
-}
-
+#endif
diff --git a/src/gsettings.c b/src/gsettings.c
new file mode 100644
index 0000000..0e91bb2
--- /dev/null
+++ b/src/gsettings.c
@@ -0,0 +1,1251 @@
+/**
+ *
+ * GSettings libccs backend
+ *
+ * gsettings.c
+ *
+ * Copyright (c) 2011 Canonical Ltd
+ *
+ * Based on the original compizconfig-backend-gconf
+ *
+ * Copyright (c) 2007 Danny Baumann <maniac@opencompositing.org>
+ *
+ * Parts of this code are taken from libberylsettings
+ * gconf backend, written by:
+ *
+ * Copyright (c) 2006 Robert Carr <racarr@opencompositing.org>
+ * Copyright (c) 2007 Dennis Kasprzyk <onestone@opencompositing.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Authored By:
+ * Sam Spilsbury <sam.spilsbury@canonical.com>
+ *
+ **/
+
+#include "gsettings.h"
+
+static void
+valueChanged (GSettings *settings,
+ gchar *keyname,
+ gpointer user_data);
+
+static void
+gnomeValueChanged (GSettings *settings,
+ gchar *keyname,
+ gpointer user_data);
+
+static GList *settingsList = NULL;
+static GSettings *compizconfigSettings = NULL;
+static GSettings *currentProfileSettings = NULL;
+static GList *watchedGnomeSettings = NULL;
+
+char *currentProfile = NULL;
+
+/* some forward declarations */
+static void writeIntegratedOption (CCSContext *context,
+ CCSSetting *setting,
+ int index);
+
+typedef struct _SpecialOptionGSettings {
+ const char* settingName;
+ const char* pluginName;
+ const char* schemaName;
+ const char* keyName;
+ const char* type;
+} SpecialOption;
+
+static gchar *
+getSchemaNameForPlugin (const char *plugin)
+{
+ gchar *schemaName = NULL;
+
+ schemaName = g_strconcat (COMPIZ_SCHEMA_ID, ".", plugin, NULL);
+
+ return schemaName;
+}
+
+static inline gchar *
+translateKeyForGSettings (char *gsettingName)
+{
+ gchar *clean = NULL;
+ gchar **delimited = NULL;
+ guint i = 0;
+
+ /* Replace underscores with dashes */
+ delimited = g_strsplit (gsettingName, "_", 0);
+
+ clean = g_strjoinv ("-", delimited);
+
+ /* It can't be more than 32 chars, warn if that's the case */
+ gchar *ret = g_strndup (clean, 31);
+
+ if (strlen (clean) > 31)
+ printf ("GSettings Backend: Warning: key name %s is not valid in GSettings, it was changed to %s, this may cause problems!\n", clean, ret);
+
+ /* Everything must be lowercase */
+ for (; i < strlen (ret); i++)
+ ret[i] = g_ascii_tolower (ret[i]);
+
+ g_free (clean);
+ g_strfreev (delimited);
+
+ return ret;
+}
+
+static inline gchar *
+translateKeyForCCS (char *gsettingName)
+{
+ gchar *clean = NULL;
+ gchar **delimited = NULL;
+
+ /* Replace dashes with underscores */
+ delimited = g_strsplit (gsettingName, "-", 0);
+
+ clean = g_strjoinv ("_", delimited);
+
+ /* FIXME: Truncated and lowercased settings aren't going to work */
+
+ g_strfreev (delimited);
+
+ return clean;
+}
+
+static GSettings *
+getSettingsObjectForPluginWithPath (const char *plugin,
+ const char *path,
+ CCSContext *context)
+{
+ GSettings *settingsObj = NULL;
+ GList *l = settingsList;
+ gchar *schemaName = getSchemaNameForPlugin (plugin);
+ GVariant *writtenPlugins;
+ char *plug;
+ GVariant *newWrittenPlugins;
+ GVariantBuilder *newWrittenPluginsBuilder;
+ GVariantIter *iter;
+ gboolean found = FALSE;
+
+ while (l)
+ {
+ settingsObj = (GSettings *) l->data;
+ gchar *name = NULL;
+
+ g_object_get (G_OBJECT (settingsObj),
+ "schema",
+ &name, NULL);
+ if (g_strcmp0 (name, schemaName) == 0)
+ {
+ g_free (name);
+ g_free (schemaName);
+
+ return settingsObj;
+ }
+
+ l = g_list_next (l);
+ }
+
+ /* No existing settings object found for this schema, create one */
+
+ settingsObj = g_settings_new_with_path (schemaName, path);
+
+ g_signal_connect (G_OBJECT (settingsObj), "changed", (GCallback) valueChanged, (gpointer) context);
+
+ settingsList = g_list_append (settingsList, (void *) settingsObj);
+
+ /* Also write the plugin name to the list of modified plugins so
+ * that when we delete the profile the keys for that profile are also
+ * unset FIXME: This could be a little more efficient, like we could
+ * store keys that have changed from their defaults ... though
+ * gsettings doesn't seem to give you a way to get all of the schemas */
+
+ writtenPlugins = g_settings_get_value (currentProfileSettings, "plugins-with-set-keys");
+
+ newWrittenPluginsBuilder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+
+ iter = g_variant_iter_new (writtenPlugins);
+ while (g_variant_iter_loop (iter, "s", &plug))
+ {
+ g_variant_builder_add (newWrittenPluginsBuilder, "s", plug);
+
+ if (!found)
+ found = (g_strcmp0 (plug, plugin) == 0);
+ }
+
+ if (!found)
+ g_variant_builder_add (newWrittenPluginsBuilder, "s", plugin);
+
+ newWrittenPlugins = g_variant_new ("as", newWrittenPluginsBuilder);
+ g_settings_set_value (currentProfileSettings, "plugins-with-set-keys", newWrittenPlugins);
+
+ g_variant_iter_free (iter);
+ g_variant_unref (newWrittenPlugins);
+ g_variant_builder_unref (newWrittenPluginsBuilder);
+
+ return settingsObj;
+}
+
+static GSettings *
+getSettingsObjectForCCSSetting (CCSSetting *setting)
+{
+ KEYNAME(setting->parent->context->screenNum);
+ PATHNAME (setting->parent->name, keyName);
+
+ return getSettingsObjectForPluginWithPath (setting->parent->name, pathName, setting->parent->context);
+}
+
+static Bool
+isIntegratedOption (CCSSetting *setting,
+ int *index)
+{
+#ifdef USE_GCONF
+ return isGConfIntegratedOption (setting, index);
+#else
+ return FALSE;
+#endif
+}
+
+static void
+gnomeValueChanged (GSettings *settings,
+ gchar *keyName,
+ gpointer user_data)
+{
+}
+
+static void
+valueChanged (GSettings *settings,
+ gchar *keyName,
+ gpointer user_data)
+{
+ CCSContext *context = (CCSContext *)user_data;
+ char *uncleanKeyName;
+ char *path;
+ char *token;
+ int index;
+ unsigned int screenNum;
+ CCSPlugin *plugin;
+ CCSSetting *setting;
+
+ g_object_get (G_OBJECT (settings), "path", &path, NULL);
+
+ path += strlen (COMPIZ) + 1;
+
+ token = strsep (&path, "/"); /* Profile name */
+ if (!token)
+ return;
+
+ token = strsep (&path, "/"); /* plugins */
+ if (!token)
+ return;
+
+ token = strsep (&path, "/"); /* plugin */
+ if (!token)
+ return;
+
+ plugin = ccsFindPlugin (context, token);
+ if (!plugin)
+ return;
+
+ token = strsep (&path, "/"); /* screen%i */
+ if (!token)
+ return;
+
+ sscanf (token, "screen%d", &screenNum);
+
+ uncleanKeyName = translateKeyForCCS (keyName);
+
+ setting = ccsFindSetting (plugin, uncleanKeyName);
+ if (!setting)
+ {
+ printf ("GSettings Backend: unable to find setting %s, for path %s\n", uncleanKeyName, path);
+ free (uncleanKeyName);
+ return;
+ }
+
+ readInit (context);
+ if (!readOption (setting))
+ {
+ ccsResetToDefault (setting);
+ }
+
+ if (ccsGetIntegrationEnabled (context) &&
+ isIntegratedOption (setting, &index))
+ {
+ writeInit (context);
+ writeIntegratedOption (context, setting, index);
+ }
+
+ free (uncleanKeyName);
+}
+
+static Bool
+readListValue (CCSSetting *setting)
+{
+ GSettings *settings = getSettingsObjectForCCSSetting (setting);
+ gchar *variantType;
+ unsigned int nItems, i = 0;
+ CCSSettingValueList list = NULL;
+ GVariant *value;
+ GVariantIter *iter;
+
+ char *cleanSettingName = translateKeyForGSettings (setting->name);
+
+ switch (setting->info.forList.listType)
+ {
+ case TypeString:
+ case TypeMatch:
+ case TypeColor:
+ variantType = g_strdup ("s");
+ break;
+ case TypeBool:
+ variantType = g_strdup ("b");
+ break;
+ case TypeInt:
+ variantType = g_strdup ("i");
+ break;
+ case TypeFloat:
+ variantType = g_strdup ("d");
+ break;
+ default:
+ variantType = NULL;
+ break;
+ }
+
+ if (!variantType)
+ return FALSE;
+
+ value = g_settings_get_value (settings, cleanSettingName);
+ if (!value)
+ {
+ ccsSetList (setting, NULL);
+ return TRUE;
+ }
+
+ iter = g_variant_iter_new (value);
+ nItems = g_variant_iter_n_children (iter);
+
+ switch (setting->info.forList.listType)
+ {
+ case TypeBool:
+ {
+ Bool *array = malloc (nItems * sizeof (Bool));
+ Bool *arrayCounter = array;
+
+ if (!array)
+ break;
+
+ /* Reads each item from the variant into the position pointed
+ * at by arrayCounter */
+ while (g_variant_iter_loop (iter, variantType, arrayCounter))
+ arrayCounter++;
+
+ list = ccsGetValueListFromBoolArray (array, nItems, setting);
+ free (array);
+ }
+ break;
+ case TypeInt:
+ {
+ int *array = malloc (nItems * sizeof (int));
+ int *arrayCounter = array;
+
+ if (!array)
+ break;
+
+ /* Reads each item from the variant into the position pointed
+ * at by arrayCounter */
+ while (g_variant_iter_loop (iter, variantType, arrayCounter))
+ arrayCounter++;
+
+ list = ccsGetValueListFromIntArray (array, nItems, setting);
+ free (array);
+ }
+ break;
+ case TypeFloat:
+ {
+ double *array = malloc (nItems * sizeof (double));
+ double *arrayCounter = array;
+
+ if (!array)
+ break;
+
+ /* Reads each item from the variant into the position pointed
+ * at by arrayCounter */
+ while (g_variant_iter_loop (iter, variantType, arrayCounter))
+ arrayCounter++;
+
+ list = ccsGetValueListFromFloatArray ((float *) array, nItems, setting);
+ free (array);
+ }
+ break;
+ case TypeString:
+ case TypeMatch:
+ {
+ char **array = calloc (1, (nItems + 1) * sizeof (char *));
+ char **arrayCounter = array;
+
+ if (!array)
+ {
+ break;
+ }
+
+ /* Reads each item from the variant into the position pointed
+ * at by arrayCounter */
+ while (g_variant_iter_loop (iter, variantType, arrayCounter))
+ arrayCounter++;
+
+ list = ccsGetValueListFromStringArray (array, nItems, setting);
+ for (i = 0; i < nItems; i++)
+ if (array[i])
+ free (array[i]);
+ free (array);
+ }
+ break;
+ case TypeColor:
+ {
+ CCSSettingColorValue *array;
+ char *colorValue;
+ array = malloc (nItems * sizeof (CCSSettingColorValue));
+ if (!array)
+ break;
+
+ while (g_variant_iter_loop (iter, variantType, &colorValue))
+ {
+ memset (&array[i], 0, sizeof (CCSSettingColorValue));
+ ccsStringToColor (colorValue,
+ &array[i]);
+ }
+ list = ccsGetValueListFromColorArray (array, nItems, setting);
+ free (array);
+ }
+ break;
+ default:
+ break;
+ }
+
+ free (cleanSettingName);
+ free (variantType);
+
+ if (list)
+ {
+ ccsSetList (setting, list);
+ ccsSettingValueListFree (list, TRUE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static Bool
+readIntegratedOption (CCSContext *context,
+ CCSSetting *setting,
+ int index)
+{
+#ifdef USE_GCONF
+ return readGConfIntegratedOption (context, setting, index);
+#else
+ return FALSE;
+#endif
+}
+
+Bool
+readOption (CCSSetting * setting)
+{
+ GSettings *settings = getSettingsObjectForCCSSetting (setting);
+ GVariant *gsettingsValue = NULL;
+ Bool ret = FALSE;
+ Bool valid = TRUE;
+
+ /* It is impossible for certain settings to have a schema,
+ * such as actions and read only settings, so in that case
+ * just return FALSE since compizconfig doesn't expect us
+ * to read them anyways */
+
+ if (setting->type == TypeAction ||
+ ccsSettingIsReadOnly (setting))
+ {
+ return FALSE;
+ }
+
+ char *cleanSettingName = translateKeyForGSettings (setting->name);
+ KEYNAME(setting->parent->context->screenNum);
+ PATHNAME (setting->parent->name, keyName);
+
+ /* first check if the key is set */
+ gsettingsValue = g_settings_get_value (settings, cleanSettingName);
+
+ switch (setting->type)
+ {
+ case TypeString:
+ case TypeMatch:
+ case TypeColor:
+ case TypeKey:
+ case TypeButton:
+ case TypeEdge:
+ valid = (g_variant_type_is_subtype_of (G_VARIANT_TYPE_STRING, g_variant_get_type (gsettingsValue)));
+ break;
+ case TypeInt:
+ valid = (g_variant_type_is_subtype_of (G_VARIANT_TYPE_INT32, g_variant_get_type (gsettingsValue)));
+ break;
+ case TypeBool:
+ case TypeBell:
+ valid = (g_variant_type_is_subtype_of (G_VARIANT_TYPE_BOOLEAN, g_variant_get_type (gsettingsValue)));
+ break;
+ case TypeFloat:
+ valid = (g_variant_type_is_subtype_of (G_VARIANT_TYPE_DOUBLE, g_variant_get_type (gsettingsValue)));
+ break;
+ case TypeList:
+ valid = (g_variant_type_is_array (g_variant_get_type (gsettingsValue)));
+ break;
+ default:
+ break;
+ }
+
+ if (!valid)
+ {
+ printf ("GSettings backend: There is an unsupported value at path %s. "
+ "Settings from this path won't be read. Try to remove "
+ "that value so that operation can continue properly.\n",
+ pathName);
+ free (cleanSettingName);
+ g_variant_unref (gsettingsValue);
+ return FALSE;
+ }
+
+ switch (setting->type)
+ {
+ case TypeString:
+ {
+ const char *value;
+ value = g_variant_get_string (gsettingsValue, NULL);
+ if (value)
+ {
+ ccsSetString (setting, value);
+ ret = TRUE;
+ }
+ }
+ break;
+ case TypeMatch:
+ {
+ const char * value;
+ value = g_variant_get_string (gsettingsValue, NULL);
+ if (value)
+ {
+ ccsSetMatch (setting, value);
+ ret = TRUE;
+ }
+ }
+ break;
+ case TypeInt:
+ {
+ int value;
+ value = g_variant_get_int32 (gsettingsValue);
+
+ ccsSetInt (setting, value);
+ ret = TRUE;
+ }
+ break;
+ case TypeBool:
+ {
+ gboolean value;
+ value = g_variant_get_boolean (gsettingsValue);
+
+ ccsSetBool (setting, value ? TRUE : FALSE);
+ ret = TRUE;
+ }
+ break;
+ case TypeFloat:
+ {
+ double value;
+ value = g_variant_get_double (gsettingsValue);
+
+ ccsSetFloat (setting, (float)value);
+ ret = TRUE;
+ }
+ break;
+ case TypeColor:
+ {
+ const char *value;
+ CCSSettingColorValue color;
+ value = g_variant_get_string (gsettingsValue, NULL);
+
+ if (value && ccsStringToColor (value, &color))
+ {
+ ccsSetColor (setting, color);
+ ret = TRUE;
+ }
+ }
+ break;
+ case TypeKey:
+ {
+ const char *value;
+ CCSSettingKeyValue key;
+ value = g_variant_get_string (gsettingsValue, NULL);
+
+ if (value && ccsStringToKeyBinding (value, &key))
+ {
+ ccsSetKey (setting, key);
+ ret = TRUE;
+ }
+ }
+ break;
+ case TypeButton:
+ {
+ const char *value;
+ CCSSettingButtonValue button;
+ value = g_variant_get_string (gsettingsValue, NULL);
+
+ if (value && ccsStringToButtonBinding (value, &button))
+ {
+ ccsSetButton (setting, button);
+ ret = TRUE;
+ }
+ }
+ break;
+ case TypeEdge:
+ {
+ const char *value;
+ value = g_variant_get_string (gsettingsValue, NULL);
+
+ if (value)
+ {
+ unsigned int edges;
+ edges = ccsStringToEdges (value);
+ ccsSetEdge (setting, edges);
+ ret = TRUE;
+ }
+ }
+ break;
+ case TypeBell:
+ {
+ gboolean value;
+ value = g_variant_get_boolean (gsettingsValue);
+
+ ccsSetBell (setting, value ? TRUE : FALSE);
+ ret = TRUE;
+ }
+ break;
+ case TypeList:
+ ret = readListValue (setting);
+ break;
+ default:
+ printf("GSettings backend: attempt to read unsupported setting type %d!\n",
+ setting->type);
+ break;
+ }
+
+ free (cleanSettingName);
+ g_variant_unref (gsettingsValue);
+
+ return ret;
+}
+
+static void
+writeListValue (CCSSetting *setting,
+ char *pathName)
+{
+ GSettings *settings = getSettingsObjectForCCSSetting (setting);
+ GVariant *value;
+ gchar *variantType = NULL;
+ CCSSettingValueList list;
+
+ char *cleanSettingName = translateKeyForGSettings (setting->name);
+
+ if (!ccsGetList (setting, &list))
+ return;
+
+ switch (setting->info.forList.listType)
+ {
+ case TypeBool:
+ {
+ variantType = "ab";
+ GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ab"));
+ while (list)
+ {
+ g_variant_builder_add (builder, "b", list->data->value.asBool);
+ list = list->next;
+ }
+ value = g_variant_new ("ab", builder);
+ g_variant_builder_unref (builder);
+ }
+ break;
+ case TypeInt:
+ {
+ variantType = "ai";
+ GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ai"));
+ while (list)
+ {
+ g_variant_builder_add (builder, "i", list->data->value.asInt);
+ list = list->next;
+ }
+ value = g_variant_new ("ai", builder);
+ g_variant_builder_unref (builder);
+ }
+ break;
+ case TypeFloat:
+ {
+ variantType = "ad";
+ GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ad"));
+ while (list)
+ {
+ g_variant_builder_add (builder, "d", (gdouble) list->data->value.asFloat);
+ list = list->next;
+ }
+ value = g_variant_new ("ad", builder);
+ g_variant_builder_unref (builder);
+ }
+ break;
+ case TypeString:
+ {
+ variantType = "as";
+ GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ while (list)
+ {
+ g_variant_builder_add (builder, "s", list->data->value.asString);
+ list = list->next;
+ }
+ value = g_variant_new ("as", builder);
+ g_variant_builder_unref (builder);
+ }
+ break;
+ case TypeMatch:
+ {
+ variantType = "as";
+ GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ while (list)
+ {
+ g_variant_builder_add (builder, "s", list->data->value.asMatch);
+ list = list->next;
+ }
+ value = g_variant_new ("as", builder);
+ g_variant_builder_unref (builder);
+ }
+ break;
+ case TypeColor:
+ {
+ variantType = "as";
+ GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ char *item;
+ while (list)
+ {
+ item = ccsColorToString (&list->data->value.asColor);
+ g_variant_builder_add (builder, "s", item);
+ list = list->next;
+ }
+ value = g_variant_new ("as", builder);
+ g_variant_builder_unref (builder);
+ }
+ break;
+ default:
+ printf("GSettings backend: attempt to write unsupported list type %d!\n",
+ setting->info.forList.listType);
+ variantType = NULL;
+ break;
+ }
+
+ if (variantType != NULL)
+ {
+ g_settings_set_value (settings, cleanSettingName, value);
+ g_variant_unref (value);
+ }
+
+ free (cleanSettingName);
+}
+
+static void
+writeIntegratedOption (CCSContext *context,
+ CCSSetting *setting,
+ int index)
+{
+#ifdef USE_GCONF
+ writeGConfIntegratedOption (context, setting, index);
+#endif
+
+ return;
+}
+
+static void
+resetOptionToDefault (CCSSetting * setting)
+{
+ GSettings *settings = getSettingsObjectForCCSSetting (setting);
+
+ char *cleanSettingName = translateKeyForGSettings (setting->name);
+ KEYNAME (setting->parent->context->screenNum);
+ PATHNAME (setting->parent->name, keyName);
+
+ g_settings_reset (settings, cleanSettingName);
+
+ free (cleanSettingName);
+}
+
+void
+writeOption (CCSSetting * setting)
+{
+ GSettings *settings = getSettingsObjectForCCSSetting (setting);
+ char *cleanSettingName = translateKeyForGSettings (setting->name);
+ KEYNAME (setting->parent->context->screenNum);
+ PATHNAME (setting->parent->name, keyName);
+
+ switch (setting->type)
+ {
+ case TypeString:
+ {
+ char *value;
+ if (ccsGetString (setting, &value))
+ {
+ g_settings_set (settings, cleanSettingName, "s", value, NULL);
+ }
+ }
+ break;
+ case TypeMatch:
+ {
+ char *value;
+ if (ccsGetMatch (setting, &value))
+ {
+ g_settings_set (settings, cleanSettingName, "s", value, NULL);
+ }
+ }
+ case TypeFloat:
+ {
+ float value;
+ if (ccsGetFloat (setting, &value))
+ {
+ g_settings_set (settings, cleanSettingName, "d", (double) value, NULL);
+ }
+ }
+ break;
+ case TypeInt:
+ {
+ int value;
+ if (ccsGetInt (setting, &value))
+ {
+ g_settings_set (settings, cleanSettingName, "i", value, NULL);
+ }
+ }
+ break;
+ case TypeBool:
+ {
+ Bool value;
+ if (ccsGetBool (setting, &value))
+ {
+ g_settings_set (settings, cleanSettingName, "b", value, NULL);
+ }
+ }
+ break;
+ case TypeColor:
+ {
+ CCSSettingColorValue value;
+ char *colString;
+
+ if (!ccsGetColor (setting, &value))
+ break;
+
+ colString = ccsColorToString (&value);
+ if (!colString)
+ break;
+
+ g_settings_set (settings, cleanSettingName, "s", value, NULL);
+ free (colString);
+ }
+ break;
+ case TypeKey:
+ {
+ CCSSettingKeyValue key;
+ char *keyString;
+
+ if (!ccsGetKey (setting, &key))
+ break;
+
+ keyString = ccsKeyBindingToString (&key);
+ if (!keyString)
+ break;
+
+ g_settings_set (settings, cleanSettingName, "s", keyString, NULL);
+ free (keyString);
+ }
+ break;
+ case TypeButton:
+ {
+ CCSSettingButtonValue button;
+ char *buttonString;
+
+ if (!ccsGetButton (setting, &button))
+ break;
+
+ buttonString = ccsButtonBindingToString (&button);
+ if (!buttonString)
+ break;
+
+ g_settings_set (settings, cleanSettingName, "s", buttonString, NULL);
+ free (buttonString);
+ }
+ break;
+ case TypeEdge:
+ {
+ unsigned int edges;
+ char *edgeString;
+
+ if (!ccsGetEdge (setting, &edges))
+ break;
+
+ edgeString = ccsEdgesToString (edges);
+ if (!edgeString)
+ break;
+
+ g_settings_set (settings, cleanSettingName, "s", edgeString, NULL);
+ free (edgeString);
+ }
+ break;
+ case TypeBell:
+ {
+ Bool value;
+ if (ccsGetBell (setting, &value))
+ {
+ g_settings_set (settings, cleanSettingName, "s", value, NULL);
+ }
+ }
+ break;
+ case TypeList:
+ writeListValue (setting, pathName);
+ break;
+ default:
+ printf("GSettings backend: attempt to write unsupported setting type %d\n",
+ setting->type);
+ break;
+ }
+
+ free (cleanSettingName);
+}
+
+static void
+updateCurrentProfileName (char *profile)
+{
+ GVariant *profiles;
+ char *prof;
+ char *profilePath = COMPIZ_PROFILEPATH;
+ char *currentProfilePath;
+ GVariant *newProfiles;
+ GVariantBuilder *newProfilesBuilder;
+ GVariantIter *iter;
+ gboolean found = FALSE;
+
+ profiles = g_settings_get_value (compizconfigSettings, "existing-profiles");
+
+ newProfilesBuilder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+
+ iter = g_variant_iter_new (profiles);
+ while (g_variant_iter_loop (iter, "s", &prof))
+ {
+ g_variant_builder_add (newProfilesBuilder, "s", prof);
+
+ if (!found)
+ found = (g_strcmp0 (prof, profile) == 0);
+ }
+
+ if (!found)
+ g_variant_builder_add (newProfilesBuilder, "s", profile);
+
+ newProfiles = g_variant_new ("as", newProfilesBuilder);
+ g_settings_set_value (compizconfigSettings, "existing-profiles", newProfiles);
+
+ g_variant_iter_free (iter);
+ g_variant_unref (newProfiles);
+ g_variant_builder_unref (newProfilesBuilder);
+
+ /* Change the current profile and current profile settings */
+ free (currentProfile);
+
+ currentProfile = strdup (profile);
+ currentProfilePath = g_strconcat (profilePath, profile, "/", NULL);
+ currentProfileSettings = g_settings_new_with_path (PROFILE_SCHEMA_ID, profilePath);
+
+ g_free (currentProfilePath);
+
+ g_settings_set (compizconfigSettings, "current-profile", "s", profile, NULL);
+}
+
+static gboolean
+updateProfile (CCSContext *context)
+{
+ char *profile = strdup (ccsGetProfile (context));
+
+ if (!profile || !strlen (profile))
+ profile = strdup (DEFAULTPROF);
+
+ if (g_strcmp0 (profile, currentProfile))
+ updateCurrentProfileName (profile);
+
+ free (profile);
+
+ return TRUE;
+}
+
+static char*
+getCurrentProfileName (void)
+{
+ GVariant *value;
+ char *ret = NULL;
+
+ value = g_settings_get_value (compizconfigSettings, "current-profile");
+
+ if (value)
+ ret = strdup (g_variant_get_string (value, NULL));
+ else
+ ret = strdup (DEFAULTPROF);
+
+ return ret;
+}
+
+static void
+processEvents (unsigned int flags)
+{
+ if (!(flags & ProcessEventsNoGlibMainLoopMask))
+ {
+ while (g_main_context_pending(NULL))
+ g_main_context_iteration(NULL, FALSE);
+ }
+}
+
+static Bool
+initBackend (CCSContext * context)
+{
+ const char *profilePath = PROFILEPATH;
+ char *currentProfilePath;
+
+ g_type_init ();
+
+ compizconfigSettings = g_settings_new (COMPIZCONFIG_SCHEMA_ID);
+
+#ifdef USE_GCONF
+ initGConfClient (context);
+#endif
+
+ currentProfile = getCurrentProfileName ();
+ currentProfilePath = g_strconcat (profilePath, currentProfile, "/", NULL);
+ currentProfileSettings = g_settings_new_with_path (PROFILE_SCHEMA_ID, currentProfilePath);
+
+ g_free (currentProfilePath);
+
+ return TRUE;
+}
+
+static Bool
+finiBackend (CCSContext * context)
+{
+ GList *l = settingsList;
+
+ processEvents (0);
+
+#ifdef USE_GCONF
+ gconf_client_clear_cache (client);
+ finiGConfClient ();
+#endif
+
+ if (currentProfile)
+ {
+ free (currentProfile);
+ currentProfile = NULL;
+ }
+
+ while (l)
+ {
+ g_object_unref (G_OBJECT (l->data));
+ l = g_list_next (l);
+ }
+
+ g_object_unref (G_OBJECT (compizconfigSettings));
+
+ processEvents (0);
+ return TRUE;
+}
+
+Bool
+readInit (CCSContext * context)
+{
+ return updateProfile (context);
+}
+
+void
+readSetting (CCSContext *context,
+ CCSSetting *setting)
+{
+ Bool status;
+ int index;
+
+ if (ccsGetIntegrationEnabled (context) &&
+ isIntegratedOption (setting, &index))
+ {
+ status = readIntegratedOption (context, setting, index);
+ }
+ else
+ status = readOption (setting);
+
+ if (!status)
+ ccsResetToDefault (setting);
+}
+
+Bool
+writeInit (CCSContext * context)
+{
+ return updateProfile (context);
+}
+
+void
+writeSetting (CCSContext *context,
+ CCSSetting *setting)
+{
+ int index;
+
+ if (ccsGetIntegrationEnabled (context) &&
+ isIntegratedOption (setting, &index))
+ {
+ writeIntegratedOption (context, setting, index);
+ }
+ else if (setting->isDefault)
+ {
+ resetOptionToDefault (setting);
+ }
+ else
+ writeOption (setting);
+
+}
+
+static Bool
+getSettingIsIntegrated (CCSSetting * setting)
+{
+ if (!ccsGetIntegrationEnabled (setting->parent->context))
+ return FALSE;
+
+ if (!isIntegratedOption (setting, NULL))
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+getSettingIsReadOnly (CCSSetting * setting)
+{
+ /* FIXME */
+ return FALSE;
+}
+
+static CCSStringList
+getExistingProfiles (CCSContext *context)
+{
+ GVariant *value;
+ char *profile;
+ GVariantIter iter;
+ CCSStringList ret = NULL;
+
+ value = g_settings_get_value (compizconfigSettings, "existing-profiles");
+ g_variant_iter_init (&iter, value);
+ while (g_variant_iter_loop (&iter, "s", &profile))
+ ret = ccsStringListAppend (ret, strdup (profile));
+
+ g_variant_unref (value);
+
+ return ret;
+}
+
+static Bool
+deleteProfile (CCSContext *context,
+ char *profile)
+{
+ GVariant *plugins;
+ GVariant *profiles;
+ GVariant *newProfiles;
+ GVariantBuilder *newProfilesBuilder;
+ char *plugin, *prof;
+ GVariantIter *iter;
+ char *profileSettingsPath = g_strconcat (PROFILEPATH, profile, "/", NULL);
+ GSettings *profileSettings = g_settings_new_with_path (PROFILE_SCHEMA_ID, profileSettingsPath);
+
+ plugins = g_settings_get_value (currentProfileSettings, "plugins-with-set-keys");
+ profiles = g_settings_get_value (compizconfigSettings, "existing-profiles");
+
+ iter = g_variant_iter_new (plugins);
+ while (g_variant_iter_loop (iter, "s", &plugin))
+ {
+ GSettings *settings;
+
+ KEYNAME (context->screenNum);
+ PATHNAME (plugin, keyName);
+
+ settings = getSettingsObjectForPluginWithPath (plugin, pathName, context);
+
+ /* The GSettings documentation says not to use this API
+ * because we should know our own schema ... though really
+ * we don't because we autogenerate schemas ... */
+ if (settings)
+ {
+ char **keys = g_settings_list_keys (settings);
+ char **key_ptr;
+
+ /* Unset all the keys */
+ for (key_ptr = keys; *key_ptr; key_ptr++)
+ g_settings_reset (settings, *key_ptr);
+
+ g_strfreev (keys);
+ }
+ }
+
+ /* Remove the profile from existing-profiles */
+ g_variant_iter_free (iter);
+ g_settings_reset (profileSettings, "plugins-with-set-values");
+
+ iter = g_variant_iter_new (profiles);
+ newProfilesBuilder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+
+ while (g_variant_iter_loop (iter, "s", &prof))
+ {
+ if (g_strcmp0 (prof, profile))
+ g_variant_builder_add (newProfilesBuilder, "s", prof);
+ }
+
+ newProfiles = g_variant_new ("as", newProfilesBuilder);
+ g_settings_set_value (compizconfigSettings, "existing-profiles", newProfiles);
+
+ g_variant_unref (newProfiles);
+ g_variant_builder_unref (newProfilesBuilder);
+
+ free (profileSettingsPath);
+
+ updateProfile (context);
+
+ return TRUE;
+}
+
+static CCSBackendVTable gsettingsVTable = {
+ "gsettings",
+ "GSettings Configuration Backend",
+ "GSettings Configuration Backend for libccs",
+ TRUE,
+ TRUE,
+ processEvents,
+ initBackend,
+ finiBackend,
+ readInit,
+ readSetting,
+ 0,
+ writeInit,
+ writeSetting,
+ 0,
+ getSettingIsIntegrated,
+ getSettingIsReadOnly,
+ getExistingProfiles,
+ deleteProfile
+};
+
+CCSBackendVTable *
+getBackendInfo (void)
+{
+ return &gsettingsVTable;
+}
+
diff --git a/src/gsettings.h b/src/gsettings.h
new file mode 100644
index 0000000..ee0d51c
--- /dev/null
+++ b/src/gsettings.h
@@ -0,0 +1,152 @@
+/**
+ *
+ * GSettings libccs backend
+ *
+ * gconf-integration.c
+ *
+ * Copyright (c) 2011 Canonical Ltd
+ *
+ * Based on the original compizconfig-backend-gconf
+ *
+ * Copyright (c) 2007 Danny Baumann <maniac@opencompositing.org>
+ *
+ * Parts of this code are taken from libberylsettings
+ * gconf backend, written by:
+ *
+ * Copyright (c) 2006 Robert Carr <racarr@opencompositing.org>
+ * Copyright (c) 2007 Dennis Kasprzyk <onestone@opencompositing.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Authored By:
+ * Sam Spilsbury <sam.spilsbury@canonical.com>
+ *
+ **/
+
+#ifndef _COMPIZCONFIG_BACKEND_GSETTINGS_GSETTINGS_H
+#define _COMPIZCONFIG_BACKEND_GSETTINGS_GSETTINGS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <string.h>
+#include <dirent.h>
+
+#include <ccs.h>
+#include <ccs-backend.h>
+
+#include <gio/gio.h>
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+
+#define CompAltMask (1 << 16)
+#define CompMetaMask (1 << 17)
+#define CompSuperMask (1 << 18)
+#define CompHyperMask (1 << 19)
+#define CompModeSwitchMask (1 << 20)
+#define CompNumLockMask (1 << 21)
+#define CompScrollLockMask (1 << 22)
+
+#define COMPIZ_SCHEMA_ID "org.freedesktop.compiz"
+#define COMPIZCONFIG_SCHEMA_ID "org.freedesktop.compizconfig"
+#define PROFILE_SCHEMA_ID "org.freedesktop.compizconfig.profile"
+#define METACITY "/apps/metacity"
+#define COMPIZ "/apps/compiz-1"
+#define COMPIZ_PROFILEPATH COMPIZ "/profiles"
+#define COMPIZCONFIG "/org/freedesktop/compizconfig"
+#define PROFILEPATH COMPIZCONFIG "/profiles"
+#define DEFAULTPROF "Default"
+#define CORE_NAME "core"
+
+#define BUFSIZE 512
+
+#define NUM_WATCHED_DIRS 3
+
+#define KEYNAME(sn) char keyName[BUFSIZE]; \
+ snprintf (keyName, BUFSIZE, "screen%i", sn);
+
+#define PATHNAME(p,k) char pathName[BUFSIZE]; \
+ if (!p || \
+ strcmp (p, "core") == 0) \
+ snprintf (pathName, BUFSIZE, \
+ "%s/%s/plugins/%s/%s/options/", COMPIZ, currentProfile, \
+ p, k); \
+ else \
+ snprintf(pathName, BUFSIZE, \
+ "%s/%s/plugins/%s/%s/options/", COMPIZ, currentProfile, \
+ p, k);
+
+#define _GNU_SOURCE
+
+typedef enum {
+ OptionInt,
+ OptionBool,
+ OptionKey,
+ OptionString,
+ OptionSpecial,
+} SpecialOptionType;
+
+char *currentProfile;
+
+Bool readInit (CCSContext * context);
+void readSetting (CCSContext * context, CCSSetting * setting);
+Bool readOption (CCSSetting * setting);
+Bool writeInit (CCSContext * context);
+void writeOption (CCSSetting *setting);
+
+#ifdef USE_GCONF
+
+#include <gconf/gconf.h>
+#include <gconf/gconf-client.h>
+#include <gconf/gconf-value.h>
+
+GConfClient *client;
+guint gnomeGConfNotifyIds[NUM_WATCHED_DIRS];
+
+typedef struct _SpecialOptionGConf {
+ const char* settingName;
+ const char* pluginName;
+ Bool screen;
+ const char* gnomeName;
+ SpecialOptionType type;
+} SpecialOptionGConf;
+
+Bool
+isGConfIntegratedOption (CCSSetting *setting,
+ int *index);
+
+void
+gnomeGConfValueChanged (GConfClient *client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer user_data);
+
+void
+initGConfClient (CCSContext *context);
+
+void
+finiGConfClient (void);
+
+Bool
+readGConfIntegratedOption (CCSContext *context,
+ CCSSetting *setting,
+ int index);
+
+void
+writeGConfIntegratedOption (CCSContext *context,
+ CCSSetting *setting,
+ int index);
+
+#endif
+
+#endif