rendered paste body/* * Copyright © 2005 Novell, Inc. * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the name of * Novell, Inc. not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * Novell, Inc. makes no representations about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. * * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: David Reveman <davidr@novell.com> *//* * source HEAVILY modified by Quinn, released under GPL */#define _GNU_SOURCE#include <string.h>#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <beryl.h>#include <glib.h>#include <glib/gprintf.h>#include <glib/gstdio.h>#include <errno.h>#define KEY_CHANGE_TIMEOUT 250static int displayPrivateIndex;enum _foo{ CSM_DISPLAY_OPTION_RELOAD, CSM_DISPLAY_OPTION_NUM};typedef struct _CSMDisplay{ int screenPrivateIndex; GKeyFile *schemaFile; // defaults in here GKeyFile *settingsFile; // user settinge here CompTimeoutHandle timeoutHandle; InitPluginForDisplayProc initPluginForDisplay; SetDisplayOptionProc setDisplayOption; SetDisplayOptionForPluginProc setDisplayOptionForPlugin; CompOption opt[CSM_DISPLAY_OPTION_NUM];} CSMDisplay;typedef struct _CSMScreen{ InitPluginForScreenProc initPluginForScreen; SetScreenOptionProc setScreenOption; SetScreenOptionForPluginProc setScreenOptionForPlugin;} CSMScreen;#define GET_CSM_DISPLAY(d) \ ((CSMDisplay *) (d)->privates[displayPrivateIndex].ptr)#define CSM_DISPLAY(d) \ CSMDisplay *gd = GET_CSM_DISPLAY (d)#define GET_CSM_SCREEN(s, gd) \ ((CSMScreen *) (s)->privates[(gd)->screenPrivateIndex].ptr)#define CSM_SCREEN(s) \ CSMScreen *gs = GET_CSM_SCREEN (s, GET_CSM_DISPLAY (s->display))#define NUM_OPTIONS(s) (sizeof ((s)->opt) / sizeof (CompOption))static gboolean set_load_option(GKeyFile * schemaFile, gchar * sect, gchar * dval, CompOption * o,CompOptionValue * v, CompDisplay * cd);static void set_save_option(GKeyFile * schemaFile, gchar * sect, gchar * dval, CompOption * o, CompDisplay * cd);static gboolean set_load_option(GKeyFile * schemaFile, gchar * sect, gchar * dval, CompOption * o,CompOptionValue * v, CompDisplay * cd){ GError * e = NULL; gboolean b; gint i; gchar * s; gdouble f; switch(o->type) { case CompOptionTypeBool: b=g_key_file_get_boolean(schemaFile,sect,dval,&e); if (!e) { v->b=b; return TRUE; } break; case CompOptionTypeInt: i=g_key_file_get_integer(schemaFile,sect,dval,&e); if (!e) { v->i=i; return TRUE; } break; case CompOptionTypeString: s=g_key_file_get_string(schemaFile,sect,dval,&e); if (s) { if (v->s) free(v->s); v->s=s; return TRUE; } break; case CompOptionTypeFloat: s=g_key_file_get_string(schemaFile,sect,dval,&e); if (s) { f=g_ascii_strtod(s,NULL); g_free(s); v->f=f; return TRUE; } break; case CompOptionTypeColor: { gint * c; gsize l=0; c=g_key_file_get_integer_list(schemaFile,sect,dval,&l,&e); if (!e && l>=4) { v->c[0]=c[0]; v->c[1]=c[1]; v->c[2]=c[2]; v->c[3]=c[3]; g_free(c); return TRUE; } } break; case CompOptionTypeAction: { gint * d; gsize l=0; d=g_key_file_get_integer_list(schemaFile,sect,dval,&l,&e); if (!e && l>=6) { v->action=o->value.action; v->action.type=CompBindingTypeNone; v->action.button.modifiers=d[0]; v->action.button.button=d[1]; if (d[1]!=0) v->action.type|=CompBindingTypeButton; v->action.key.modifiers=d[2]; v->action.key.keycode=0; if (d[3]!=0) { v->action.key.keycode=XKeysymToKeycode(cd->display,d[3]); v->action.type|=CompBindingTypeKey; } v->action.edgeMask=d[4]; v->action.bell=d[5]==1?TRUE:FALSE; g_free(d); return TRUE; } } break; case CompOptionTypeList: { gint i; v->list.type = o->value.list.type; switch(o->value.list.type) { gsize l=0; case CompOptionTypeBool: { gboolean * d = g_key_file_get_boolean_list( schemaFile,sect,dval,&l,&e); if (!e) { if (v->list.nValue && v->list.value) { v->list.nValue=0; free(v->list.value); } v->list.nValue=l; v->list.value=malloc(sizeof(CompOptionValue)*l); for (i=0;i<l;i++) v->list.value[i].b=d[i]; g_free(d); return TRUE; } } break; case CompOptionTypeInt: { gint * d = g_key_file_get_integer_list( schemaFile,sect,dval,&l,&e); if (!e) { if (v->list.nValue && v->list.value) { v->list.nValue=0; free(v->list.value); } v->list.nValue=l; v->list.value=malloc(sizeof(CompOptionValue)*l); for (i=0;i<l;i++) v->list.value[i].i=d[i]; g_free(d); return TRUE; } } break; case CompOptionTypeString: { gchar ** d = g_key_file_get_string_list(schemaFile,sect, dval,&l,&e); if (!e) { if (v->list.nValue && v->list.value) { v->list.nValue=0; free(v->list.value); } v->list.nValue=l; v->list.value=malloc(sizeof(CompOptionValue)*l); for(i=0;i<l;i++) { if (!d[i]) v->list.value[i].s=strdup(""); else v->list.value[i].s=strdup(d[i]); } g_strfreev(d); return TRUE; } } break; case CompOptionTypeFloat: { gchar ** d = g_key_file_get_string_list(schemaFile,sect, dval,&l,&e); if (!e) { if (v->list.nValue && v->list.value) { v->list.nValue=0; free(v->list.value); } v->list.nValue=l; v->list.value=malloc(sizeof(CompOptionValue)*l); for(i=0;i<l;i++) v->list.value[i].f=g_ascii_strtod(d[i],NULL); g_strfreev(d); return TRUE; } } break; case CompOptionTypeAction: { gint * d = g_key_file_get_integer_list( schemaFile,sect,dval,&l,&e); if (!e && l%6==0) { if (v->list.nValue && v->list.value) { v->list.nValue=0; free(v->list.value); } v->list.nValue=l/6; v->list.value=malloc(sizeof(CompOptionValue)*l); for(i=0;i<(l/6);i++) { v->list.value[i].action.button.modifiers=d[i*6]; v->list.value[i].action.button.button=d[i*6+1]; v->list.value[i].action.key.modifiers=d[i*6+2]; v->list.value[i].action.key.keycode= XKeysymToKeycode(cd->display,d[i*6+3]); v->list.value[i].action.edgeMask=d[i*6+4]; v->list.value[i].action.bell=d[i*6+5]==1?TRUE:FALSE; } g_free(d); return TRUE; } } break; case CompOptionTypeColor: { gint * d = g_key_file_get_integer_list( schemaFile,sect,dval,&l,&e); if (!e && l%4==0) { if (v->list.nValue && v->list.value) { v->list.nValue=0; free(v->list.value); } v->list.nValue=l/4; v->list.value=malloc(sizeof(CompOptionValue)*l); for(i=0;i<(l/4);i++) { v->list.value[i].c[0]=d[i*4]; v->list.value[i].c[1]=d[i*4+1]; v->list.value[i].c[2]=d[i*4+2]; v->list.value[i].c[3]=d[i*4+3]; } g_free(d); } return TRUE; } break; case CompOptionTypeList: g_error("List type is not a valid list type"); } } } return FALSE;}static void set_save_option(GKeyFile * schemaFile, gchar * sect, gchar * dval, CompOption * o, CompDisplay * cd){ switch(o->type) { case CompOptionTypeBool: g_key_file_set_boolean(schemaFile,sect,dval,o->value.b); break; case CompOptionTypeInt: g_key_file_set_integer(schemaFile,sect,dval,o->value.i); break; case CompOptionTypeString: g_key_file_set_string(schemaFile,sect,dval,o->value.s); break; case CompOptionTypeFloat: { gchar s[G_ASCII_DTOSTR_BUF_SIZE]; g_ascii_dtostr(s,G_ASCII_DTOSTR_BUF_SIZE,o->value.f); g_key_file_set_string(schemaFile,sect,dval,s); } break; case CompOptionTypeColor: { gint c[4]; c[0]=o->value.c[0]; c[1]=o->value.c[1]; c[2]=o->value.c[2]; c[3]=o->value.c[3]; g_key_file_set_integer_list(schemaFile,sect,dval,c,4); } break; case CompOptionTypeAction: { //format... //string list //button;key;edge;bell; //button-format // modifiers(int);button(int); //key-format // modifiers(int);keysym(int); //edge-format // edgemask(int) //bell-format // on_bell(int) gint d[6]; d[0]=o->value.action.button.modifiers; d[1]=(o->value.action.type & CompBindingTypeButton)? o->value.action.button.button:0; d[2]=o->value.action.key.modifiers; d[3]=(o->value.action.type & CompBindingTypeKey)? XKeycodeToKeysym(cd->display,o->value.action.key.keycode,0) :0; d[4]=o->value.action.edgeMask; d[5]=o->value.action.bell?1:0; g_key_file_set_integer_list(schemaFile,sect,dval,d,6); } break; case CompOptionTypeList: { gint i; switch(o->value.list.type) { case CompOptionTypeBool: { gboolean * d = malloc(sizeof(gboolean)*o->value.list.nValue); for (i=0;i<o->value.list.nValue;i++) d[i]=o->value.list.value[i].b; g_key_file_set_boolean_list(schemaFile,sect,dval,d,o->value.list.nValue); free(d); } break; case CompOptionTypeInt: { gint * d = malloc(sizeof(gint)*o->value.list.nValue); for (i=0;i<o->value.list.nValue;i++) d[i]=o->value.list.value[i].i; g_key_file_set_integer_list(schemaFile,sect,dval,d,o->value.list.nValue); free(d); } break; case CompOptionTypeString: { gchar ** d = malloc(sizeof(gchar *)*o->value.list.nValue); for(i=0;i<o->value.list.nValue;i++) d[i]=o->value.list.value[i].s; g_key_file_set_string_list(schemaFile,sect,dval, (const gchar **)d,o->value.list.nValue); free(d); } break; case CompOptionTypeFloat: { gchar ** d = malloc(sizeof(gchar *)*o->value.list.nValue); for (i=0;i<o->value.list.nValue;i++) { d[i]=malloc(G_ASCII_DTOSTR_BUF_SIZE); g_ascii_dtostr(d[i],G_ASCII_DTOSTR_BUF_SIZE, o->value.list.value[i].f); } g_key_file_set_string_list(schemaFile,sect,dval, (const gchar **) d,o->value.list.nValue); for (i=0;i<o->value.list.nValue;i++) free(d[i]); free(d); } break; case CompOptionTypeAction: { gint * d = malloc(sizeof(gint)*o->value.list.nValue*6); for(i=0;i<o->value.list.nValue;i++) { d[i*6]=o->value.list.value[i].action.button.modifiers; d[i*6+1]=(o->value.list.value[i].action.type & CompBindingTypeButton) ?o->value.list.value[i].action.button.button:0; d[i*6+2]=o->value.list.value[i].action.key.modifiers; d[i*6+3]=(o->value.list.value[i].action.type & CompBindingTypeKey) ?XKeycodeToKeysym(cd->display, o->value.list.value[i].action.key.keycode,0):0; d[i*6+4]=o->value.list.value[i].action.edgeMask; d[i*6+5]=o->value.list.value[i].action.bell?1:0; } g_key_file_set_integer_list(schemaFile,sect,dval,d, o->value.list.nValue*6); free(d); } break; case CompOptionTypeColor: { gint * d = malloc(sizeof(gint)*o->value.list.nValue*4); for(i=0;i<o->value.list.nValue;i++) { gint j; for(j=0;j<4;j++) { d[i*4+j]=o->value.list.value[i].c[j]; } } g_key_file_set_integer_list(schemaFile,sect,dval,d, o->value.list.nValue*4); free(d); } break; case CompOptionTypeList: g_error("List type is not a valid list type"); } } }}static CompOption *setGetDisplayOptions (CompDisplay * display, int *count){ if (display) { CSM_DISPLAY (display); *count = NUM_OPTIONS (gd); return gd->opt; } else { *count=0; return NULL; }}static gbooleanset_compare_option (CompOption * o, CompOption * p){ //check if o == p if (o->type != p->type) return FALSE; if (o->type == CompOptionTypeList && (o->value.list.type != p->value.list.type || o->value.list.nValue != p->value.list.nValue)) return FALSE; switch (o->type) { case CompOptionTypeString: if (!o->value.s || !p->value.s || strcmp (o->value.s, p->value.s) != 0) return FALSE; // if only one is NULL this isn't quite right, but it //shouldn't happen break; case CompOptionTypeFloat: if (o->value.f != p->value.f) return FALSE; break; case CompOptionTypeInt: if (o->value.i != p->value.i) return FALSE; break; case CompOptionTypeColor: { gint i; for (i = 0; i < 4; i++) if (o->value.c[i] != p->value.c[i]) return FALSE; } break; case CompOptionTypeBool: if (o->value.b != p->value.b) return FALSE; break; case CompOptionTypeAction: if (o->value.action.type != p->value.action.type) return FALSE; if (o->value.action.button.button != p->value.action.button.button) return FALSE; if (o->value.action.button.modifiers != p->value.action.button.modifiers) return FALSE; if (o->value.action.key.keycode != p->value.action.key.keycode) return FALSE; if (o->value.action.key.modifiers != p->value.action.key.modifiers) return FALSE; if (o->value.action.edgeMask != p->value.action.edgeMask) return FALSE; if (o->value.action.bell != p->value.action.bell) return FALSE; break; case CompOptionTypeList: { gint i; for (i = 0; i < o->value.list.nValue; i++) { CompOption a, b; a.type = o->value.list.type; b.type = p->value.list.type; a.value = o->value.list.value[i]; b.value = p->value.list.value[i]; if (!set_compare_option (&a, &b)) return FALSE; } } } return TRUE;}static voidsetSetOption (CompDisplay * d, CompOption * o, gboolean screen, gchar * plugin){ gchar *key; gchar *key2; CompOption p; CSM_DISPLAY (d); if (!screen) key = g_strconcat ("a_", o->name, NULL); else key = g_strconcat ("s_", o->name, NULL); key2 = g_strconcat ("d_", key, NULL); if (!plugin) plugin = "_"; p.name = o->name; p.type = o->type; if (o->type == CompOptionTypeString) p.value.s = NULL; if (o->type == CompOptionTypeList) { p.value.list.type = o->value.list.type; p.value.list.nValue = 0; p.value.list.value = 0; } p.rest = o->rest; if ((!set_load_option (gd->settingsFile, plugin, key, o, &p.value, d) && !set_load_option (gd->schemaFile, plugin, key2, o, &p.value, d)) || !set_compare_option (o, &p)) { /*if (screen && strcmp(screen,"allscreens")!=0) { if (plugin) d->screens->setScreenOptionForPlugin(d->screens,plugin,p.name,&(p.value)); else d->screens->setScreenOption(d->screens,p.name,&(p.value)); } else { if (plugin) d->setDisplayOptionForPlugin(d,plugin,p.name,&(p.value)); else d->setDisplayOption(d,p.name,&(p.value)); } */ set_save_option (gd->settingsFile, plugin, key, &p, d); { gchar *fnam = g_strconcat (g_get_home_dir (), "/.beryl/settings", NULL); gchar *set = g_key_file_to_data (gd->settingsFile, NULL, NULL); if (set) { FILE *f = fopen (fnam, "w"); if (!f) g_warning (strerror (errno)); else { fprintf (f, "%s", set); fclose (f); } g_free (set); } g_free (fnam); } } if (p.type == CompOptionTypeList && p.value.list.nValue && p.value.list.value) { if (p.value.list.type == CompOptionTypeString) { gint i; for (i = 0; i < p.value.list.nValue; i++) free (p.value.list.value[i].s); } free (p.value.list.value); } if (p.type == CompOptionTypeString) free (p.value.s); g_free (key); g_free (key2);}static voidsetInitOption (CompDisplay * d, CompOption * o, gboolean screen, gchar * plugin){ gchar *key, *key2; CompScreen *s = d->screens; CompOptionValue *v = malloc (sizeof (CompOptionValue)); gboolean stat; CSM_DISPLAY (d); bzero (v, sizeof (CompOptionValue)); if (!plugin) plugin = "_"; if (!screen) key = g_strconcat ("a_", o->name, NULL); else key = g_strconcat ("s_", o->name, NULL); key2 = g_strconcat ("d_", key, NULL); stat = set_load_option (gd->settingsFile, plugin, key, o, v, d); if (!stat) stat = set_load_option (gd->schemaFile, plugin, key2, o, v, d); if (!stat) { g_warning ("bailing, couldn't find a val for %s in \n" "[%s]->%s or\n" "[%s]->%s", o->name, plugin, key, plugin, key2); return; } if (screen) { if (strcmp (plugin, "_") != 0) { s->setScreenOptionForPlugin (s, plugin, o->name, v); } else { s->setScreenOption (s, o->name, v); } } else { if (strcmp (plugin, "_") != 0) { d->setDisplayOptionForPlugin (d, plugin, o->name, v); } else { d->setDisplayOption (d, o->name, v); } } free (v);}static BoolreloadProc (CompDisplay * d, CompAction * action, CompActionState state, CompOption * option, int nOption){ CSM_DISPLAY (d); gchar *sect, *opt; CompOption *o = NULL; CompPlugin *p; CompScreen *s = NULL; int oc = 0; GError *e = NULL; opt = g_strconcat (g_get_home_dir (), "/.beryl/settings", NULL); g_key_file_free (gd->settingsFile); gd->settingsFile = g_key_file_new (); g_key_file_load_from_file (gd->settingsFile, opt, 0, &e); if (e) g_warning ("couldn't load settings file!"); g_free (opt); sect = getStringOptionNamed (option, nOption, "section", 0); if (!sect) return TRUE; opt = getStringOptionNamed (option, nOption, "option", 0); if (!opt) return TRUE; if (strlen (opt) < 3) return TRUE; if (opt[0] == 's') { s = d->screens; } p = findActivePlugin (sect); if (p) { if (s) { if (p->vTable->getScreenOptions) o = (*p->vTable->getScreenOptions) (s, &oc); } else { if (p->vTable->getDisplayOptions) o = (*p->vTable->getDisplayOptions) (d, &oc); } } else { if (s) o = compGetScreenOptions (s, &oc); else o = compGetDisplayOptions (d, &oc); } o = compFindOption (o, oc, opt + 2, 0); if (o) { g_message ("Reloading for [%s]->%s(%s)", sect, opt, o->name); setInitOption (d, o, opt[0] == 's', sect); return FALSE; } else g_warning ("Couldn't find [%s]->%s", sect, opt); return TRUE;}static BoolsetSetDisplayOption (CompDisplay * d, char *name, CompOptionValue * value){ Bool status; CSM_DISPLAY (d); UNWRAP (gd, d, setDisplayOption); status = (*d->setDisplayOption) (d, name, value); WRAP (gd, d, setDisplayOption, setSetDisplayOption); if (status) { CompOption *option; int nOption; option = compGetDisplayOptions (d, &nOption); setSetOption (d, compFindOption (option, nOption, name, 0), FALSE, 0); } return status;}static BoolsetSetDisplayOptionForPlugin (CompDisplay * d, char *plugin, char *name, CompOptionValue * value){ Bool status; CSM_DISPLAY (d); UNWRAP (gd, d, setDisplayOptionForPlugin); status = (*d->setDisplayOptionForPlugin) (d, plugin, name, value); WRAP (gd, d, setDisplayOptionForPlugin, setSetDisplayOptionForPlugin); if (status) { CompPlugin *p; p = findActivePlugin (plugin); if (p && p->vTable->getDisplayOptions) { CompOption *option; int nOption; option = (*p->vTable->getDisplayOptions) (d, &nOption); setSetOption (d, compFindOption (option, nOption, name, 0), FALSE, plugin); } } return status;}static BoolsetSetScreenOption (CompScreen * s, char *name, CompOptionValue * value){ Bool status; CSM_SCREEN (s); UNWRAP (gs, s, setScreenOption); status = (*s->setScreenOption) (s, name, value); WRAP (gs, s, setScreenOption, setSetScreenOption); if (status) { CompOption *option; int nOption; option = compGetScreenOptions (s, &nOption); setSetOption (s->display, compFindOption (option, nOption, name, 0), TRUE, 0); } return status;}static BoolsetSetScreenOptionForPlugin (CompScreen * s, char *plugin, char *name, CompOptionValue * value){ Bool status; CSM_SCREEN (s); UNWRAP (gs, s, setScreenOptionForPlugin); status = (*s->setScreenOptionForPlugin) (s, plugin, name, value); WRAP (gs, s, setScreenOptionForPlugin, setSetScreenOptionForPlugin); if (status) { CompPlugin *p; p = findActivePlugin (plugin); if (p && p->vTable->getScreenOptions) { CompOption *option; int nOption; option = (*p->vTable->getScreenOptions) (s, &nOption); setSetOption (s->display, compFindOption (option, nOption, name, 0), TRUE, plugin); } } return status;}static BoolsetInitPluginForDisplay (CompPlugin * p, CompDisplay * d){ Bool status; CSM_DISPLAY (d); UNWRAP (gd, d, initPluginForDisplay); status = (*d->initPluginForDisplay) (p, d); WRAP (gd, d, initPluginForDisplay, setInitPluginForDisplay); if (status && p->vTable->getDisplayOptions) { CompOption *option; int nOption; option = (*p->vTable->getDisplayOptions) (d, &nOption); while (nOption--) setInitOption (d, option++, FALSE, p->vTable->name); } return status;}static BoolsetInitPluginForScreen (CompPlugin * p, CompScreen * s){ Bool status; CSM_SCREEN (s); UNWRAP (gs, s, initPluginForScreen); status = (*s->initPluginForScreen) (p, s); WRAP (gs, s, initPluginForScreen, setInitPluginForScreen); if (status && p->vTable->getScreenOptions) { CompOption *option; int nOption; option = (*p->vTable->getScreenOptions) (s, &nOption); while (nOption--) setInitOption (s->display, option++, TRUE, p->vTable->name); } return status;}static BoolsetTimeout (void *closure){ while (g_main_pending ()) g_main_iteration (FALSE); return TRUE;}static voidsetDisplayInitOptions (CSMDisplay * gd){ CompOption *o; o = &gd->opt[CSM_DISPLAY_OPTION_RELOAD]; o->name = "reload"; o->shortDesc = N_("Reload"); o->longDesc = N_("DBUS Signal Target for Reload"); o->type = CompOptionTypeAction; o->value.action.initiate = reloadProc; o->value.action.terminate = 0; o->value.action.bell = FALSE; o->value.action.edgeMask = 0; o->value.action.state = 0; o->value.action.type = CompBindingTypeNone;}static voidimport_key_file (GKeyFile * dest, gchar * source){ GKeyFile *f = g_key_file_new (); gchar **gr; gint i; g_key_file_load_from_file (f, source, 0, NULL); gr = g_key_file_get_groups (f, NULL); for (i = 0; gr && gr[i]; i++) { gint j; gchar **ke; ke = g_key_file_get_keys (f, gr[i], NULL, NULL); for (j = 0; ke && ke[j]; j++) g_key_file_set_value (dest, gr[i], ke[j], g_key_file_get_value (f, gr[i], ke[j], NULL)); g_strfreev (ke); } g_strfreev (gr); g_key_file_free (f);}static voidload_schema_files (CSMDisplay * gd){ GDir *d; gchar *dpos; gd->schemaFile = g_key_file_new (); import_key_file (gd->schemaFile, DATADIR "/beryl/settings"); d = g_dir_open (DATADIR "/beryl/", 0, NULL); if (d) { const gchar *e; while ((e = g_dir_read_name (d))) { gchar *xfile; if (g_str_has_suffix (e, ".settings")) { xfile = g_strconcat (DATADIR "/beryl/", e, NULL); import_key_file (gd->schemaFile, xfile); g_free (xfile); } } g_dir_close (d); } dpos = g_strconcat (g_get_home_dir (), "/.beryl/plugins/", NULL); d = g_dir_open (dpos, 0, NULL); if (d) { const gchar *e; while ((e = g_dir_read_name (d))) { gchar *xfile; if (g_str_has_suffix (e, ".settings")) { xfile = g_strconcat (g_get_home_dir (), "/.beryl/plugins/", e, NULL); import_key_file (gd->schemaFile, xfile); g_free (xfile); } } g_dir_close (d); } g_free (dpos);}static BoolsetInitDisplay (CompPlugin * p, CompDisplay * d){ CompOption *option; int nOption; CSMDisplay *gd; gchar *smmser; gd = malloc (sizeof (CSMDisplay)); if (!gd) return FALSE; setDisplayInitOptions (gd); gd->screenPrivateIndex = allocateScreenPrivateIndex (d); if (gd->screenPrivateIndex < 0) { free (gd); return FALSE; } WRAP (gd, d, initPluginForDisplay, setInitPluginForDisplay); WRAP (gd, d, setDisplayOption, setSetDisplayOption); WRAP (gd, d, setDisplayOptionForPlugin, setSetDisplayOptionForPlugin); d->privates[displayPrivateIndex].ptr = gd; load_schema_files (gd); gd->settingsFile = g_key_file_new (); smmser = g_strconcat (g_get_home_dir (), "/.beryl", NULL); g_mkdir_with_parents (smmser, 00755); g_chmod (smmser, 00755); g_free (smmser); smmser = g_strconcat (g_get_home_dir (), "/.beryl/settings", NULL); g_key_file_load_from_file (gd->settingsFile, smmser, 0, NULL); g_free (smmser); option = compGetDisplayOptions (d, &nOption); while (nOption--) setInitOption (d, option++, FALSE, 0); gd->timeoutHandle = compAddTimeout (KEY_CHANGE_TIMEOUT, setTimeout, 0); return TRUE;}static voidsetFiniDisplay (CompPlugin * p, CompDisplay * d){ CSM_DISPLAY (d); g_key_file_free (gd->schemaFile); g_key_file_free (gd->settingsFile); compRemoveTimeout (gd->timeoutHandle); freeScreenPrivateIndex (d, gd->screenPrivateIndex); free (gd);}static BoolsetInitScreen (CompPlugin * p, CompScreen * s){ CompOption *option; int nOption; CSMScreen *gs; CSM_DISPLAY (s->display); gs = malloc (sizeof (CSMScreen)); if (!gs) return FALSE; WRAP (gs, s, initPluginForScreen, setInitPluginForScreen); WRAP (gs, s, setScreenOption, setSetScreenOption); WRAP (gs, s, setScreenOptionForPlugin, setSetScreenOptionForPlugin); s->privates[gd->screenPrivateIndex].ptr = gs; option = compGetScreenOptions (s, &nOption); while (nOption--) setInitOption (s->display, option++, TRUE, 0); return TRUE;}static voidsetFiniScreen (CompPlugin * p, CompScreen * s){ CSM_SCREEN (s); UNWRAP (gs, s, initPluginForScreen); UNWRAP (gs, s, setScreenOption); UNWRAP (gs, s, setScreenOptionForPlugin); free (gs);}static BoolsetInit (CompPlugin * p){ displayPrivateIndex = allocateDisplayPrivateIndex (); if (displayPrivateIndex < 0) return FALSE; return TRUE;}static voidsetFini (CompPlugin * p){ if (displayPrivateIndex >= 0) freeDisplayPrivateIndex (displayPrivateIndex);}CompPluginDep setDeps[] = { {CompPluginRuleAfter, "dbus"} , {CompPluginRuleBefore, "decoration"} , {CompPluginRuleBefore, "wobbly"} , {CompPluginRuleBefore, "fade"} , {CompPluginRuleBefore, "cube"} , {CompPluginRuleBefore, "scale"}};CompPluginVTable setVTable = { "settings", "Settings Manager", "Use beryl-settings to configure me!", setInit, setFini, setInitDisplay, setFiniDisplay, setInitScreen, setFiniScreen, 0, /* InitWindow */ 0, /* FiniWindow */ setGetDisplayOptions, /* GetDisplayOptions */// not forever 0, /* SetDisplayOption */ 0, /* GetScreenOptions */ 0, /* SetScreenOption */ setDeps, sizeof (setDeps) / sizeof (setDeps[0]), BERYL_ABI_INFO};CompPluginVTable *getCompPluginInfo (void){ return &setVTable;}