/** * * GConf libccs backend * * gconf.c * * Copyright (c) 2007 Danny Baumann * * Parts of this code are taken from libberylsettings * gconf backend, written by: * * Copyright (c) 2006 Robert Carr * Copyright (c) 2007 Dennis Kasprzyk * * 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. * **/ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #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" #define COMPIZCONFIG "/apps/compizconfig" #define PROFILEPATH COMPIZCONFIG "/profiles" #define DEFAULTPROF "Default" #define CORE_NAME "core" #define BUFSIZE 512 #define KEYNAME char keyName[BUFSIZE]; \ if (setting->isScreen) \ snprintf (keyName, BUFSIZE, "screen%d", \ setting->screenNum); \ else \ snprintf (keyName, BUFSIZE, "allscreens"); #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[] = { {"run", "core", FALSE, METACITY "/global_keybindings/panel_run_dialog", OptionKey}, {"main_menu", "core", FALSE, METACITY "/global_keybindings/panel_main_menu", OptionKey}, {"run_command_screenshot", "core", FALSE, METACITY "/global_keybindings/run_command_screenshot", OptionKey}, {"run_command_window_screenshot", "core", FALSE, METACITY "/global_keybindings/run_command_window_screenshot", OptionKey}, {"run_command_terminal", "core", FALSE, METACITY "/global_keybindings/run_command_terminal", OptionKey}, {"toggle_window_maximized", "core", FALSE, METACITY "/window_keybindings/toggle_maximized", OptionKey}, {"minimize_window", "core", FALSE, METACITY "/window_keybindings/minimize", OptionKey}, {"maximize_window", "core", FALSE, METACITY "/window_keybindings/maximize", OptionKey}, {"unmaximize_window", "core", FALSE, METACITY "/window_keybindings/unmaximize", OptionKey}, {"maximize_window_horizontally", "core", FALSE, METACITY "/window_keybindings/maximize_horizontally", OptionKey}, {"maximize_window_vertically", "core", FALSE, METACITY "/window_keybindings/maximize_vertically", OptionKey}, {"raise_window", "core", FALSE, METACITY "/window_keybindings/raise", OptionKey}, {"lower_window", "core", FALSE, METACITY "/window_keybindings/lower", OptionKey}, {"close_window", "core", FALSE, METACITY "/window_keybindings/close", OptionKey}, {"toggle_window_shaded", "core", FALSE, METACITY "/window_keybindings/toggle_shaded", OptionKey}, {"show_desktop", "core", FALSE, METACITY "/global_keybindings/show_desktop", OptionKey}, {"initiate", "move", FALSE, METACITY "/window_keybindings/begin_move", OptionSpecial}, {"initiate", "resize", FALSE, METACITY "/window_keybindings/begin_resize", OptionSpecial}, {"window_menu", "core", FALSE, METACITY "/window_keybindings/activate_window_menu", OptionSpecial}, /* this option does not exist in Compiz */ {"mouse_button_modifier", NULL, FALSE, METACITY "/general/mouse_button_modifier", OptionSpecial}, {"visual_bell", "fade", TRUE, METACITY "/general/visual_bell", OptionBool}, {"fullscreen_visual_bell", "fade", TRUE, METACITY "/general/visual_bell_type", OptionSpecial}, {"next", "switcher", FALSE, METACITY "/global_keybindings/switch_windows", OptionKey}, {"prev", "switcher", FALSE, METACITY "/global_keybindings/switch_windows_backward", OptionKey}, {"toggle_sticky", "extrawm", FALSE, METACITY "/window_keybindings/toggle_on_all_workspaces", OptionKey}, {"toggle_fullscreen", "extrawm", FALSE, METACITY "/window_keybindings/toggle_fullscreen", OptionKey}, {"command0", "core", FALSE, METACITY "/keybinding_commands/command_1", OptionString}, {"command1", "core", FALSE, METACITY "/keybinding_commands/command_2", OptionString}, {"command2", "core", FALSE, METACITY "/keybinding_commands/command_3", OptionString}, {"command3", "core", FALSE, METACITY "/keybinding_commands/command_4", OptionString}, {"command4", "core", FALSE, METACITY "/keybinding_commands/command_5", OptionString}, {"command5", "core", FALSE, METACITY "/keybinding_commands/command_6", OptionString}, {"command6", "core", FALSE, METACITY "/keybinding_commands/command_7", OptionString}, {"command7", "core", FALSE, METACITY "/keybinding_commands/command_8", OptionString}, {"command8", "core", FALSE, METACITY "/keybinding_commands/command_9", OptionString}, {"command9", "core", FALSE, METACITY "/keybinding_commands/command_10", OptionString}, {"command10", "core", FALSE, METACITY "/keybinding_commands/command_11", OptionString}, {"command11", "core", FALSE, METACITY "/keybinding_commands/command_12", OptionString}, {"run_command0", "core", FALSE, METACITY "/global_keybindings/run_command_1", OptionKey}, {"run_command1", "core", FALSE, METACITY "/global_keybindings/run_command_2", OptionKey}, {"run_command2", "core", FALSE, METACITY "/global_keybindings/run_command_3", OptionKey}, {"run_command3", "core", FALSE, METACITY "/global_keybindings/run_command_4", OptionKey}, {"run_command4", "core", FALSE, METACITY "/global_keybindings/run_command_5", OptionKey}, {"run_command5", "core", FALSE, METACITY "/global_keybindings/run_command_6", OptionKey}, {"run_command6", "core", FALSE, METACITY "/global_keybindings/run_command_7", OptionKey}, {"run_command7", "core", FALSE, METACITY "/global_keybindings/run_command_8", OptionKey}, {"run_command8", "core", FALSE, METACITY "/global_keybindings/run_command_9", OptionKey}, {"run_command9", "core", FALSE, METACITY "/global_keybindings/run_command_10", OptionKey}, {"run_command10", "core", FALSE, METACITY "/global_keybindings/run_command_11", OptionKey}, {"run_command11", "core", FALSE, METACITY "/global_keybindings/run_command_12", OptionKey}, {"rotate_to_1", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_1", OptionKey}, {"rotate_to_2", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_2", OptionKey}, {"rotate_to_3", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_3", OptionKey}, {"rotate_to_4", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_4", OptionKey}, {"rotate_to_5", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_5", OptionKey}, {"rotate_to_6", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_6", OptionKey}, {"rotate_to_7", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_7", OptionKey}, {"rotate_to_8", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_8", OptionKey}, {"rotate_to_9", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_9", OptionKey}, {"rotate_to_10", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_10", OptionKey}, {"rotate_to_11", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_11", OptionKey}, {"rotate_to_12", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_12", OptionKey}, {"rotate_left", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_left", OptionKey}, {"rotate_right", "rotate", FALSE, METACITY "/global_keybindings/switch_to_workspace_right", OptionKey}, {"plane_to_1", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_1", OptionKey}, {"plane_to_2", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_2", OptionKey}, {"plane_to_3", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_3", OptionKey}, {"plane_to_4", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_4", OptionKey}, {"plane_to_5", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_5", OptionKey}, {"plane_to_6", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_6", OptionKey}, {"plane_to_7", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_7", OptionKey}, {"plane_to_8", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_8", OptionKey}, {"plane_to_9", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_9", OptionKey}, {"plane_to_10", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_10", OptionKey}, {"plane_to_11", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_11", OptionKey}, {"plane_to_12", "plane", FALSE, METACITY "/global_keybindings/switch_to_workspace_12", OptionKey}, {"switch_to_1", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_1", OptionKey}, {"switch_to_2", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_2", OptionKey}, {"switch_to_3", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_3", OptionKey}, {"switch_to_4", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_4", OptionKey}, {"switch_to_5", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_5", OptionKey}, {"switch_to_6", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_6", OptionKey}, {"switch_to_7", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_7", OptionKey}, {"switch_to_8", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_8", OptionKey}, {"switch_to_9", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_9", OptionKey}, {"switch_to_10", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_10", OptionKey}, {"switch_to_11", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_11", OptionKey}, {"switch_to_12", "vpswitch", FALSE, METACITY "/global_keybindings/switch_to_workspace_12", OptionKey}, {"up", "wall", FALSE, METACITY "/global_keybindings/switch_to_workspace_up", OptionKey}, {"down", "wall", FALSE, METACITY "/global_keybindings/switch_to_workspace_down", OptionKey}, {"left", "wall", FALSE, METACITY "/global_keybindings/switch_to_workspace_left", OptionKey}, {"right", "wall", FALSE, METACITY "/global_keybindings/switch_to_workspace_right", OptionKey}, {"left_window", "wall", FALSE, METACITY "/window_keybindings/move_to_workspace_left", OptionKey}, {"right_window", "wall", FALSE, METACITY "/window_keybindings/move_to_workspace_right", OptionKey}, {"up_window", "wall", FALSE, METACITY "/window_keybindings/move_to_workspace_up", OptionKey}, {"down_window", "wall", FALSE, METACITY "/window_keybindings/move_to_workspace_down", OptionKey}, {"put_topleft", "put", FALSE, METACITY "/window_keybindings/move_to_corner_nw", OptionKey}, {"put_topright", "put", FALSE, METACITY "/window_keybindings/move_to_corner_ne", OptionKey}, {"put_bottomleft", "put", FALSE, METACITY "/window_keybindings/move_to_corner_sw", OptionKey}, {"put_bottomright", "put", FALSE, METACITY "/window_keybindings/move_to_corner_se", OptionKey}, {"put_left", "put", FALSE, METACITY "/window_keybindings/move_to_side_w", OptionKey}, {"put_right", "put", FALSE, METACITY "/window_keybindings/move_to_side_e", OptionKey}, {"put_top", "put", FALSE, METACITY "/window_keybindings/move_to_side_n", OptionKey}, {"put_bottom", "put", FALSE, METACITY "/window_keybindings/move_to_side_s", OptionKey}, {"rotate_to_1_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_1", OptionKey}, {"rotate_to_2_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_2", OptionKey}, {"rotate_to_3_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_3", OptionKey}, {"rotate_to_4_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_4", OptionKey}, {"rotate_to_5_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_5", OptionKey}, {"rotate_to_6_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_6", OptionKey}, {"rotate_to_7_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_7", OptionKey}, {"rotate_to_8_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_8", OptionKey}, {"rotate_to_9_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_9", OptionKey}, {"rotate_to_10_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_10", OptionKey}, {"rotate_to_11_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_11", OptionKey}, {"rotate_to_12_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_12", OptionKey}, {"rotate_left_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_left", OptionKey}, {"rotate_right_window", "rotate", FALSE, METACITY "/window_keybindings/move_to_workspace_right", OptionKey}, {"command_screenshot", "core", FALSE, METACITY "/keybinding_commands/command_screenshot", OptionString}, {"command_window_screenshot", "core", FALSE, METACITY "/keybinding_commands/command_window_screenshot", OptionString}, {"command_terminal", "core", FALSE, "/desktop/gnome/applications/terminal/exec", OptionString}, {"current_viewport", "thumbnail", TRUE, "/apps/panel/applets/window_list/prefs/display_all_workspaces", OptionSpecial}, {"autoraise", "core", FALSE, METACITY "/general/auto_raise", OptionBool}, {"autoraise_delay", "core", FALSE, METACITY "/general/auto_raise_delay", OptionInt}, {"raise_on_click", "core", FALSE, METACITY "/general/raise_on_click", OptionBool}, {"click_to_focus", "core", FALSE, METACITY "/general/focus_mode", OptionSpecial}, {"audible_bell", "core", FALSE, METACITY "/general/audible_bell", OptionBool}, /*{"hsize", "core", TRUE, METACITY "/general/num_workspaces", OptionInt},*/ }; #define N_SOPTIONS (sizeof (specialOptions) / sizeof (struct _SpecialOption)) static CCSSetting * findDisplaySettingForPlugin (CCSContext *context, char *plugin, char *setting) { CCSPlugin *p; CCSSetting *s; p = ccsFindPlugin (context, plugin); if (!p) return NULL; s = ccsFindSetting (p, setting, FALSE, 0); if (!s) return NULL; return s; } static Bool isIntegratedOption (CCSSetting *setting, int *index) { unsigned int i; for (i = 0; i < N_SOPTIONS; i++) { if ((strcmp (setting->name, specialOptions[i].settingName) == 0) && ((!setting->parent->name && !specialOptions[i].pluginName) || (setting->parent->name && specialOptions[i].pluginName && (strcmp (setting->parent->name, specialOptions[i].pluginName) == 0))) && ((setting->isScreen && specialOptions[i].screen) || (!setting->isScreen && !specialOptions[i].screen))) { if (index) *index = i; return TRUE; } } 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; if (strcmp (token, "allscreens") == 0) isScreen = FALSE; else { isScreen = TRUE; sscanf (token, "screen%d", &screenNum); } token = strsep (&keyName, "/"); /* 'options' */ if (!token) return; token = strsep (&keyName, "/"); if (!token) return; setting = ccsFindSetting (plugin, token, isScreen, screenNum); if (!setting) { /* maybe it's an action which has a name_button/... naming scheme */ const char *prefix[] = { "_key", "_button", "_edge", "_edgebutton", "_bell" }; int i; int prefixLen, len = strlen (token); for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++) { prefixLen = strlen (prefix[i]); if (len < prefixLen) continue; if (strcmp (token + len - prefixLen, prefix[i]) == 0) { char *buffer = malloc (sizeof (char) * (len - prefixLen + 1)); if (buffer) { strncpy (buffer, token, len - prefixLen); buffer[len - prefixLen] = 0; setting = ccsFindSetting (plugin, buffer, isScreen, screenNum); free (buffer); } break; } } } 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) { CCSContext *context = (CCSContext *)user_data; char *keyName = (char*) gconf_entry_get_key (entry); int i, last = 0, num = 0; Bool needInit = TRUE; if (!ccsGetIntegrationEnabled (context)) return; /* we have to loop multiple times here, because one Gnome option may be integrated with multiple Compiz options */ while (1) { for (i = last, num = -1; i < N_SOPTIONS; i++) { if (strcmp (specialOptions[i].gnomeName, keyName) == 0) { num = i; last = i + 1; break; } } if (num < 0) break; if (strcmp (specialOptions[num].settingName, "mouse_button_modifier") == 0) { CCSSetting *s; if (needInit) { readInit (context); needInit = FALSE; } s = findDisplaySettingForPlugin (context, "core", "window_menu"); if (s) readSetting (context, s); s = findDisplaySettingForPlugin (context, "move", "initiate"); if (s) readSetting (context, s); s = findDisplaySettingForPlugin (context, "resize", "initiate"); if (s) readSetting (context, s); } else { CCSPlugin *plugin = NULL; CCSSetting *setting; SpecialOption *opt = (SpecialOption *) &specialOptions[num]; plugin = ccsFindPlugin (context, (char*) opt->pluginName); if (plugin) { for (i = 0; i < context->numScreens; i++) { unsigned int screen; if (opt->screen) screen = context->screens[i]; else screen = 0; setting = ccsFindSetting (plugin, (char*) opt->settingName, opt->screen, screen); if (setting) { if (needInit) { readInit (context); needInit = FALSE; } readSetting (context, setting); } /* do not read display settings multiple times for multiscreen environments */ if (!opt->screen) i = context->numScreens; } } } } } static void initClient (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); for (i = 0; i < NUM_WATCHED_DIRS; i++) { gnomeNotifyIds[i] = gconf_client_notify_add (client, watchedGnomeDirectories[i], gnomeValueChanged, context, NULL, NULL); gconf_client_add_dir (client, watchedGnomeDirectories[i], GCONF_CLIENT_PRELOAD_NONE, NULL); } } static void finiClient (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]) { gconf_client_notify_remove (client, gnomeNotifyIds[0]); gnomeNotifyIds[i] = 0; } gconf_client_remove_dir (client, watchedGnomeDirectories[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); value = gconf_engine_get_without_default (conf, key, NULL); if (value && newKey) { if (newSchema) gconf_engine_associate_schema (conf, newKey, newSchema, NULL); 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 (to) { if (newKey) free (newKey); } else 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 readActionValue (CCSSetting *setting, char *pathName) { char itemPath[BUFSIZE]; GError *err = NULL; Bool ret = FALSE; GConfValue *gconfValue; CCSSettingActionValue action; memset (&action, 0, sizeof (CCSSettingActionValue)); snprintf (itemPath, 512, "%s_bell", pathName); gconfValue = gconf_client_get (client, itemPath, &err); if (!err && gconfValue) { action.onBell = gconf_value_get_bool (gconfValue); ret = TRUE; } if (err) { g_error_free (err); err = NULL; } if (gconfValue) gconf_value_free (gconfValue); snprintf (itemPath, 512, "%s_edge", pathName); gconfValue = gconf_client_get (client, itemPath, &err); if (!err && gconfValue) { if ((gconfValue->type == GCONF_VALUE_LIST) && (gconf_value_get_list_type (gconfValue) == GCONF_VALUE_STRING)) { GSList *list; CCSStringList edgeList = NULL; list = gconf_value_get_list (gconfValue); for ( ; list; list = list->next) { GConfValue *value = (GConfValue *) list->data; const char *edge = gconf_value_get_string (value); if (edge) edgeList = ccsStringListAppend (edgeList, (char*) edge); } ccsStringListToEdges (edgeList, &action); if (edgeList) ccsStringListFree (edgeList, FALSE); } } if (err) { g_error_free (err); err = NULL; } if (gconfValue) gconf_value_free (gconfValue); snprintf (itemPath, 512, "%s_edgebutton", pathName); gconfValue = gconf_client_get (client, itemPath, &err); if (!err && gconfValue) { action.edgeButton = gconf_value_get_int (gconfValue); ret = TRUE; } if (err) { g_error_free (err); err = NULL; } if (gconfValue) gconf_value_free (gconfValue); snprintf (itemPath, 512, "%s_key", pathName); gconfValue = gconf_client_get (client, itemPath, &err); if (!err && gconfValue) { const char* buffer; buffer = gconf_value_get_string (gconfValue); if (buffer) { ccsStringToKeyBinding (buffer, &action); ret = TRUE; } } if (err) { g_error_free (err); err = NULL; } if (gconfValue) gconf_value_free (gconfValue); snprintf (itemPath, 512, "%s_button", pathName); gconfValue = gconf_client_get (client, itemPath, &err); if (!err && gconfValue) { const char* buffer; buffer = gconf_value_get_string (gconfValue); if (buffer) { ccsStringToButtonBinding (buffer, &action); ret = TRUE; } } if (err) { g_error_free (err); err = NULL; } if (gconfValue) gconf_value_free (gconfValue); if (ret) ccsSetAction (setting, action); return ret; } 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) { unsigned int modMask = 0; GError *err = NULL; char *value; value = gconf_client_get_string (client, METACITY "/general/mouse_button_modifier", &err); if (err) { g_error_free (err); return 0; } if (!value) return 0; modMask = ccsStringToModifiers (value); g_free (value); return modMask; } static Bool readIntegratedOption (CCSContext *context, CCSSetting *setting, int index) { GError *err = NULL; Bool ret = FALSE; switch (specialOptions[index].type) { case OptionInt: { guint value; value = gconf_client_get_int (client, specialOptions[index].gnomeName, &err); if (!err) { ccsSetInt (setting, value); ret = TRUE; } } break; case OptionBool: { gboolean value; value = gconf_client_get_bool (client, specialOptions[index].gnomeName, &err); if (!err) { ccsSetBool (setting, value ? TRUE : FALSE); ret = TRUE; } } break; case OptionString: { char *value; value = gconf_client_get_string (client, specialOptions[index].gnomeName, &err); if (!err && value) { ccsSetString (setting, value); ret = TRUE; g_free (value); } } break; case OptionKey: { char *value; value = gconf_client_get_string (client, specialOptions[index].gnomeName, &err); if (!err && value) { CCSSettingActionValue action; memset (&action, 0, sizeof(CCSSettingActionValue)); ccsGetAction (setting, &action); if (strcasecmp (value, "disabled") == 0) { /* clear out keybinding */ action.keysym = NoSymbol; action.keyModMask = 0; ccsSetAction (setting, action); ret = TRUE; } else if (ccsStringToKeyBinding (value, &action)) { ccsSetAction (setting, action); ret = TRUE; } g_free (value); } } break; case OptionSpecial: { const char *settingName = specialOptions[index].settingName; const char *pluginName = specialOptions[index].pluginName; if (strcmp (settingName, "current_viewport") == 0) { const char *name; gboolean showAll; name = specialOptions[index].gnomeName; showAll = gconf_client_get_bool (client, name, &err); if (!err) { ccsSetBool (setting, !showAll); ret = TRUE; } } else if (strcmp (settingName, "fullscreen_visual_bell") == 0) { const char *name; char *value; name = specialOptions[index].gnomeName; value = gconf_client_get_string (client, name, &err); if (!err && value) { Bool fullscreen; fullscreen = strcmp (value, "fullscreen") == 0; ccsSetBool (setting, fullscreen); ret = TRUE; g_free (value); } } else if (strcmp (settingName, "click_to_focus") == 0) { char *focusMode; const char *name; name = specialOptions[index].gnomeName; focusMode = gconf_client_get_string (client, name, &err); if (!err && focusMode) { Bool clickToFocus = (strcmp (focusMode, "click") == 0); ccsSetBool (setting, clickToFocus); ret = TRUE; g_free (focusMode); } } else if (((strcmp (settingName, "initiate") == 0) && ((strcmp (pluginName, "move") == 0) || (strcmp (pluginName, "resize") == 0))) || (strcmp (settingName, "window_menu") == 0)) { char *value; const char *name; name = specialOptions[index].gnomeName; value = gconf_client_get_string (client, name, &err); if (!err && value) { CCSSettingActionValue action; memset (&action, 0, sizeof(CCSSettingActionValue)); ccsGetAction (setting, &action); if (strcasecmp (value, "disabled") == 0) { /* clear out keybinding */ action.keysym = NoSymbol; action.keyModMask = 0; } if ((strcasecmp (value, "disabled") == 0) || ccsStringToKeyBinding (value, &action)) { action.buttonModMask = getGnomeMouseButtonModifier (); if (strcmp (settingName, "window_menu") == 0) action.button = 3; else if (strcmp (pluginName, "resize") == 0) action.button = 2; else action.button = 1; ccsSetAction (setting, action); ret = TRUE; } g_free (value); } } } break; default: break; } if (err) g_error_free (err); return ret; } static Bool readOption (CCSSetting * setting) { GConfValue *gconfValue = NULL; GError *err = NULL; Bool ret = FALSE; KEYNAME; PATHNAME; /* first check if the key is set, but only if the setting type is not action - actions are in a subtree and handled separately */ if (setting->type != TypeAction) { Bool valid = TRUE; 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: valid = (gconfValue->type == GCONF_VALUE_STRING); break; case TypeInt: valid = (gconfValue->type == GCONF_VALUE_INT); break; case TypeBool: 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 TypeList: ret = readListValue (setting, gconfValue); break; case TypeAction: ret = readActionValue (setting, pathName); break; default: printf("GConf backend: attempt to read unsupported setting type %d!\n", setting->type); break; } if (gconfValue) gconf_value_free (gconfValue); return ret; } static void writeActionValue(CCSSettingActionValue *action, char *pathName) { char *buffer; char itemPath[BUFSIZE]; CCSStringList edgeList, l; GSList *list = NULL; snprintf (itemPath, BUFSIZE, "%s_edge", pathName); edgeList = ccsEdgesToStringList (action); for (l = edgeList; l; l = l->next) list = g_slist_append (list, l->data); gconf_client_set_list (client, itemPath, GCONF_VALUE_STRING, list, NULL); if (edgeList) ccsStringListFree (edgeList, TRUE); if (list) g_slist_free (list); snprintf (itemPath, BUFSIZE, "%s_bell", pathName); gconf_client_set_bool (client, itemPath, action->onBell, NULL); snprintf (itemPath, BUFSIZE, "%s_edgebutton", pathName); gconf_client_set_int (client, itemPath, action->edgeButton, NULL); snprintf (itemPath, BUFSIZE, "%s_button", pathName); buffer = ccsButtonBindingToString (action); if (buffer) { gconf_client_set_string (client, itemPath, buffer, NULL); free (buffer); } snprintf (itemPath, BUFSIZE, "%s_key", pathName); buffer = ccsKeyBindingToString (action); if (buffer) { gconf_client_set_string (client, itemPath, buffer, NULL); free (buffer); } } 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: { float *item; while (list) { item = malloc (sizeof (float)); 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!\n", setting->info.forList.listType); 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 void setGnomeMouseButtonModifier (unsigned int modMask) { char *modifiers, *currentValue; GError *err = NULL; modifiers = ccsModifiersToString (modMask); if (!modifiers) modifiers = strdup (""); if (!modifiers) return; currentValue = gconf_client_get_string(client, METACITY "/general/mouse_button_modifier", &err); if (err) { free (modifiers); g_error_free (err); return; } if (!currentValue || (strcmp (currentValue, modifiers) != 0)) gconf_client_set_string (client, METACITY "/general/mouse_button_modifier", modifiers, NULL); if (currentValue) g_free (currentValue); free (modifiers); } static void setButtonBindingForSetting (CCSContext *context, const char *plugin, const char *setting, unsigned int button, unsigned int buttonModMask) { CCSSetting *s; CCSSettingActionValue action; s = findDisplaySettingForPlugin (context, (char*) plugin, (char*) setting); if (!s) return; if (s->type != TypeAction) return; action = s->value->value.asAction; if ((action.button != button) || (action.buttonModMask != buttonModMask)) { action.button = button; action.buttonModMask = buttonModMask; ccsSetAction (s, action); } } static void writeIntegratedOption (CCSContext *context, CCSSetting *setting, int index) { GError *err = NULL; const char *optionName = specialOptions[index].gnomeName; switch (specialOptions[index].type) { case OptionInt: { int newValue, currentValue; if (!ccsGetInt (setting, &newValue)) break; currentValue = gconf_client_get_int (client, optionName, &err); if (!err && (currentValue != newValue)) gconf_client_set_int(client, specialOptions[index].gnomeName, newValue, NULL); } break; case OptionBool: { Bool newValue; gboolean currentValue; if (!ccsGetBool (setting, &newValue)) break; currentValue = gconf_client_get_bool (client, optionName, &err); if (!err && ((currentValue && !newValue) || (!currentValue && newValue))) gconf_client_set_bool (client, specialOptions[index].gnomeName, newValue, NULL); } break; case OptionString: { char *newValue; gchar *currentValue; if (!ccsGetString (setting, &newValue)) break; currentValue = gconf_client_get_string (client, optionName, &err); if (!err && currentValue) { if (strcmp (currentValue, newValue) != 0) gconf_client_set_string (client, optionName, newValue, NULL); g_free (currentValue); } } break; case OptionKey: { char *newValue; gchar *currentValue; newValue = ccsKeyBindingToString (&setting->value->value.asAction); if (newValue && !strlen (newValue)) { free (newValue); newValue = NULL; } if (!newValue) newValue = strdup ("disabled"); if (newValue) { currentValue = gconf_client_get_string(client, optionName, &err); if (!err && currentValue) { if (strcmp (currentValue, newValue) != 0) gconf_client_set_string (client, optionName, newValue, NULL); g_free (currentValue); } free (newValue); } } break; case OptionSpecial: { const char *settingName = specialOptions[index].settingName; const char *pluginName = specialOptions[index].pluginName; if (strcmp (settingName, "current_viewport") == 0) { Bool currentViewport; if (!ccsGetBool (setting, ¤tViewport)) break; gconf_client_set_bool (client, optionName, !currentViewport, NULL); } else if (strcmp (settingName, "fullscreen_visual_bell") == 0) { Bool fullscreen; gchar *currentValue, *newValue; if (!ccsGetBool (setting, &fullscreen)) break; newValue = fullscreen ? "fullscreen" : "frame_flash"; currentValue = gconf_client_get_string (client, optionName, &err); if (!err && currentValue) { if (strcmp (currentValue, newValue) != 0) gconf_client_set_string (client, optionName, newValue, NULL); g_free (currentValue); } } else if (strcmp (settingName, "click_to_focus") == 0) { Bool clickToFocus; gchar *newValue, *currentValue; if (!ccsGetBool (setting, &clickToFocus)) break; newValue = clickToFocus ? "click" : "mouse"; currentValue = gconf_client_get_string (client, optionName, &err); if (!err && currentValue) { if (strcmp (currentValue, newValue) != 0) gconf_client_set_string (client, optionName, newValue, NULL); g_free (currentValue); } } else if (((strcmp (settingName, "initiate") == 0) && ((strcmp (pluginName, "move") == 0) || (strcmp (pluginName, "resize") == 0))) || (strcmp (settingName, "window_menu") == 0)) { char *newValue; gchar *currentValue; unsigned int modMask; modMask = setting->value->value.asAction.buttonModMask; newValue = ccsKeyBindingToString (&setting->value->value.asAction); if (newValue && !strlen (newValue)) { free (newValue); newValue = NULL; } if (!newValue) newValue = strdup ("disabled"); if (newValue) { currentValue = gconf_client_get_string(client, optionName, &err); if (!err && currentValue) { if (strcmp (currentValue, newValue) != 0) gconf_client_set_string(client, optionName, newValue, NULL); g_free (currentValue); } free (newValue); } setGnomeMouseButtonModifier (modMask); setButtonBindingForSetting (context, "move", "initiate", 1, modMask); setButtonBindingForSetting (context, "resize", "initiate", 2, modMask); setButtonBindingForSetting (context, "core", "window_menu", 3, modMask); } } break; } if (err) g_error_free (err); } static void resetOptionToDefault (CCSSetting * setting) { KEYNAME; PATHNAME; if (setting->type != TypeAction) gconf_client_recursive_unset (client, pathName, 0, NULL); else { char itemPath[BUFSIZE]; snprintf (itemPath, BUFSIZE, "%s_edge", pathName); gconf_client_recursive_unset (client, itemPath, 0, NULL); snprintf (itemPath, BUFSIZE, "%s_edgebutton", pathName); gconf_client_recursive_unset (client, itemPath, 0, NULL); snprintf (itemPath, BUFSIZE, "%s_button", pathName); gconf_client_recursive_unset (client, itemPath, 0, NULL); snprintf (itemPath, BUFSIZE, "%s_key", pathName); gconf_client_recursive_unset (client, itemPath, 0, NULL); snprintf (itemPath, BUFSIZE, "%s_bell", pathName); gconf_client_recursive_unset (client, itemPath, 0, NULL); } gconf_client_suggest_sync (client, NULL); } static void writeOption (CCSSetting * setting) { KEYNAME; 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 TypeAction: { CCSSettingActionValue value; if (!ccsGetAction (setting, &value)) break; writeActionValue (&value, pathName); } 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"); 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 (strcmp (lastProfile, currentProfile) != 0) { char *pathName; /* copy /apps/compiz tree to profile path */ asprintf (&pathName, "%s/%s", PROFILEPATH, lastProfile); if (pathName) { copyGconfTree (context, "/apps/compiz", pathName, TRUE, "/schemas/apps/compiz"); free (pathName); } /* reset /apps/compiz tree */ gconf_client_recursive_unset (client, COMPIZ, 0, NULL); /* copy new profile tree to /apps/compiz */ asprintf (&pathName, "%s/%s", PROFILEPATH, currentProfile); if (pathName) { copyGconfTree (context, pathName, COMPIZ, FALSE, NULL); /* delete the new profile tree in /apps/compizconfig 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; }