~compiz-team/compiz/0.9.12

« back to all changes in this revision

Viewing changes to compizconfig/gconf/src/gconf.c

  • Committer: CI Train Bot
  • Author(s): Marco Trevisan (Treviño)
  • Date: 2015-12-11 10:00:29 UTC
  • mfrom: (3988.2.3 compiz)
  • Revision ID: ci-train-bot@canonical.com-20151211100029-5tq13bj2xvpejtdv
backends: drop gconf support
Approved by: Sebastien Bacher

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 *
3
 
 * GConf libccs backend
4
 
 *
5
 
 * gconf.c
6
 
 *
7
 
 * Copyright (c) 2007 Danny Baumann <maniac@opencompositing.org>
8
 
 *
9
 
 * Parts of this code are taken from libberylsettings 
10
 
 * gconf backend, written by:
11
 
 *
12
 
 * Copyright (c) 2006 Robert Carr <racarr@opencompositing.org>
13
 
 * Copyright (c) 2007 Dennis Kasprzyk <onestone@opencompositing.org>
14
 
 *
15
 
 * This program is free software; you can redistribute it and/or
16
 
 * modify it under the terms of the GNU General Public License
17
 
 * as published by the Free Software Foundation; either version 2
18
 
 * of the License, or (at your option) any later version.
19
 
 *
20
 
 * This program is distributed in the hope that it will be useful,
21
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 
 * GNU General Public License for more details.
24
 
 *
25
 
 **/
26
 
 
27
 
#define CCS_LOG_DOMAIN "gconf"
28
 
 
29
 
#define _GNU_SOURCE
30
 
#include <stdio.h>
31
 
#include <stdlib.h>
32
 
#include <string.h>
33
 
#include <malloc.h>
34
 
#include <string.h>
35
 
#include <dirent.h>
36
 
 
37
 
#include <ccs.h>
38
 
#include <ccs-backend.h>
39
 
 
40
 
#include <X11/X.h>
41
 
#include <X11/Xlib.h>
42
 
 
43
 
#include <gconf/gconf.h>
44
 
#include <gconf/gconf-client.h>
45
 
#include <gconf/gconf-value.h>
46
 
 
47
 
#include "ccs_gnome_integration.h"
48
 
#include "ccs_gnome_integration_gconf_integrated_setting_factory.h"
49
 
 
50
 
#define COMPIZ       "/apps/compiz-1"
51
 
#define COMPIZCONFIG "/apps/compizconfig-1"
52
 
#define PROFILEPATH  COMPIZCONFIG "/profiles"
53
 
#define DEFAULTPROF "Default"
54
 
#define CORE_NAME   "core"
55
 
 
56
 
#define BUFSIZE 512
57
 
 
58
 
#define KEYNAME(sn)     char keyName[BUFSIZE]; \
59
 
                    snprintf (keyName, BUFSIZE, "screen%i", sn);
60
 
 
61
 
#define PATHNAME    char pathName[BUFSIZE]; \
62
 
                    if (!ccsPluginGetName (ccsSettingGetParent (setting)) || \
63
 
                        strcmp (ccsPluginGetName (ccsSettingGetParent (setting)), "core") == 0) \
64
 
                        snprintf (pathName, BUFSIZE, \
65
 
                                 "%s/general/%s/options/%s", COMPIZ, \
66
 
                                 keyName, ccsSettingGetName (setting)); \
67
 
                    else \
68
 
                        snprintf(pathName, BUFSIZE, \
69
 
                                 "%s/plugins/%s/%s/options/%s", COMPIZ, \
70
 
                                 ccsPluginGetName (ccsSettingGetParent (setting)), keyName, ccsSettingGetName (setting));
71
 
 
72
 
static GConfClient *client = NULL;
73
 
static GConfEngine *conf = NULL;
74
 
static guint compizNotifyId;
75
 
static char *currentProfile = NULL;
76
 
static CCSGNOMEValueChangeData valueChangeData =
77
 
{
78
 
    NULL,
79
 
    NULL,
80
 
    NULL,
81
 
    NULL
82
 
};
83
 
 
84
 
/* some forward declarations */
85
 
static Bool readInit (CCSBackend *backend, CCSContext * context);
86
 
static void readSetting (CCSBackend *backend, CCSContext * context, CCSSetting * setting);
87
 
static Bool readOption (CCSSetting * setting);
88
 
static Bool writeInit (CCSBackend *backend, CCSContext * context);
89
 
static void writeIntegratedOption (CCSContext *context, CCSSetting *setting, CCSIntegratedSetting *integrated);
90
 
 
91
 
static Bool
92
 
isIntegratedOption (CCSSetting *setting,
93
 
                    CCSIntegratedSetting **integrated)
94
 
{
95
 
    CCSPlugin    *plugin = ccsSettingGetParent (setting);
96
 
    const char   *pluginName = ccsPluginGetName (plugin);
97
 
    const char   *settingName = ccsSettingGetName (setting);
98
 
    CCSIntegratedSetting *tmp = ccsIntegrationGetIntegratedSetting (valueChangeData.integration, pluginName, settingName);
99
 
 
100
 
    if (integrated)
101
 
        *integrated = tmp;
102
 
 
103
 
    return tmp != NULL;
104
 
}
105
 
 
106
 
static void
107
 
updateSetting (CCSBackend *backend, CCSContext *context, CCSPlugin *plugin, CCSSetting *setting)
108
 
{
109
 
    CCSIntegratedSetting *integrated;
110
 
    readInit (backend, context);
111
 
    if (!readOption (setting))
112
 
        ccsResetToDefault (setting, TRUE);
113
 
 
114
 
    if (ccsGetIntegrationEnabled (context) &&
115
 
        isIntegratedOption (setting, &integrated))
116
 
    {
117
 
        writeInit (backend, context);
118
 
        writeIntegratedOption (context, setting, integrated);
119
 
    }
120
 
}
121
 
 
122
 
static void
123
 
valueChanged (GConfClient *client,
124
 
              guint       cnxn_id,
125
 
              GConfEntry  *entry,
126
 
              gpointer    user_data)
127
 
{
128
 
    CCSContext   *context = (CCSContext *)user_data;
129
 
    char         *keyName = (char*) gconf_entry_get_key (entry);
130
 
    char         *pluginName;
131
 
    char         *token;
132
 
    unsigned int screenNum;
133
 
    CCSPlugin    *plugin;
134
 
    CCSSetting   *setting;
135
 
 
136
 
    keyName += strlen (COMPIZ) + 1;
137
 
 
138
 
    token = strsep (&keyName, "/"); /* plugin */
139
 
    if (!token)
140
 
        return;
141
 
 
142
 
    if (strcmp (token, "general") == 0)
143
 
    {
144
 
        pluginName = "core";
145
 
    }
146
 
    else
147
 
    {
148
 
        token = strsep (&keyName, "/");
149
 
        if (!token)
150
 
            return;
151
 
        pluginName = token;
152
 
    }
153
 
 
154
 
    plugin = ccsFindPlugin (context, pluginName);
155
 
    if (!plugin)
156
 
        return;
157
 
 
158
 
    token = strsep (&keyName, "/");
159
 
    if (!token)
160
 
        return;
161
 
 
162
 
    sscanf (token, "screen%d", &screenNum);
163
 
 
164
 
    token = strsep (&keyName, "/"); /* 'options' */
165
 
    if (!token)
166
 
        return;
167
 
 
168
 
    token = strsep (&keyName, "/");
169
 
    if (!token)
170
 
        return;
171
 
 
172
 
    setting = ccsFindSetting (plugin, token);
173
 
    if (!setting)
174
 
        return;
175
 
 
176
 
    /* Passing null here is not optimal, but we are not
177
 
     * maintaining gconf actively here */
178
 
    updateSetting (NULL, context, plugin, setting);
179
 
}
180
 
 
181
 
static void
182
 
initClient (CCSBackend *backend, CCSContext *context)
183
 
{
184
 
    client = gconf_client_get_for_engine (conf);
185
 
 
186
 
    valueChangeData.context = context;
187
 
    valueChangeData.storage = ccsIntegratedSettingsStorageDefaultImplNew (&ccsDefaultObjectAllocator);
188
 
    valueChangeData.factory = ccsGConfIntegratedSettingFactoryNew (client, &valueChangeData, &ccsDefaultObjectAllocator);
189
 
 
190
 
    valueChangeData.integration = ccsGNOMEIntegrationBackendNew (backend,
191
 
                                                                 context,
192
 
                                                                 valueChangeData.factory,
193
 
                                                                 valueChangeData.storage,
194
 
                                                                 &ccsDefaultObjectAllocator);
195
 
 
196
 
    compizNotifyId = gconf_client_notify_add (client, COMPIZ, valueChanged,
197
 
                                              context, NULL, NULL);
198
 
    gconf_client_add_dir (client, COMPIZ, GCONF_CLIENT_PRELOAD_NONE, NULL);
199
 
}
200
 
 
201
 
static void
202
 
finiClient (void)
203
 
{
204
 
    ccsIntegrationUnref (valueChangeData.integration);
205
 
 
206
 
    if (compizNotifyId)
207
 
    {
208
 
        gconf_client_notify_remove (client, compizNotifyId);
209
 
        compizNotifyId = 0;
210
 
    }
211
 
    gconf_client_remove_dir (client, COMPIZ, NULL);
212
 
    gconf_client_suggest_sync (client, NULL);
213
 
 
214
 
    g_object_unref (client);
215
 
    client = NULL;
216
 
 
217
 
    memset (&valueChangeData, 0, sizeof (CCSGNOMEValueChangeData));
218
 
}
219
 
 
220
 
static void
221
 
copyGconfValues (GConfEngine *conf,
222
 
                 const gchar *from,
223
 
                 const gchar *to,
224
 
                 Bool        associate,
225
 
                 const gchar *schemaPath)
226
 
{
227
 
    GSList *values, *tmp;
228
 
    GError *err = NULL;
229
 
 
230
 
    values = gconf_engine_all_entries (conf, from, &err);
231
 
    tmp = values;
232
 
 
233
 
    while (tmp)
234
 
    {
235
 
        GConfEntry *entry = tmp->data;
236
 
        const char *key = gconf_entry_get_key (entry);
237
 
        char       *name, *newKey, *newSchema = NULL;
238
 
 
239
 
        name = strrchr (key, '/');
240
 
        if (!name)
241
 
            continue;
242
 
 
243
 
        if (to)
244
 
        {
245
 
            GConfValue *value;
246
 
 
247
 
            if (asprintf (&newKey, "%s/%s", to, name + 1) == -1)
248
 
                newKey = NULL;
249
 
 
250
 
            if (associate && schemaPath)
251
 
                if (asprintf (&newSchema, "%s/%s", schemaPath, name + 1) == -1)
252
 
                    newSchema = NULL;
253
 
 
254
 
            if (newKey && newSchema)
255
 
                gconf_engine_associate_schema (conf, newKey, newSchema, NULL);
256
 
 
257
 
            if (newKey)
258
 
            {
259
 
                value = gconf_engine_get_without_default (conf, key, NULL);
260
 
                if (value)
261
 
                {
262
 
                    gconf_engine_set (conf, newKey, value, NULL);
263
 
                    gconf_value_free (value);
264
 
                }
265
 
            }
266
 
 
267
 
            if (newSchema)
268
 
                free (newSchema);
269
 
            if (newKey)
270
 
                free (newKey);
271
 
        }
272
 
        else
273
 
        {
274
 
            if (associate)
275
 
                gconf_engine_associate_schema (conf, key, NULL, NULL);
276
 
            gconf_engine_unset (conf, key, NULL);
277
 
        }
278
 
 
279
 
        gconf_entry_unref (entry);
280
 
        tmp = g_slist_next (tmp);
281
 
    }
282
 
 
283
 
    if (values)
284
 
        g_slist_free (values);
285
 
}
286
 
 
287
 
static void
288
 
copyGconfRecursively (GConfEngine *conf,
289
 
                      GSList      *subdirs,
290
 
                      const gchar *to,
291
 
                      Bool        associate,
292
 
                      const gchar *schemaPath)
293
 
{
294
 
    GSList* tmp;
295
 
 
296
 
    tmp = subdirs;
297
 
 
298
 
    while (tmp)
299
 
    {
300
 
        gchar *path = tmp->data;
301
 
        char  *newKey, *newSchema = NULL, *name;
302
 
 
303
 
        name = strrchr (path, '/');
304
 
        if (name)
305
 
        {
306
 
            if (!(to && asprintf (&newKey, "%s/%s", to, name + 1) != -1))
307
 
                newKey = NULL;
308
 
 
309
 
            if (associate && schemaPath)
310
 
                if (asprintf (&newSchema, "%s/%s", schemaPath, name + 1) == -1)
311
 
                    newSchema = NULL;
312
 
 
313
 
            copyGconfValues (conf, path, newKey, associate, newSchema);
314
 
            copyGconfRecursively (conf,
315
 
                                  gconf_engine_all_dirs (conf, path, NULL),
316
 
                                  newKey, associate, newSchema);
317
 
 
318
 
            if (newSchema)
319
 
                free (newSchema);
320
 
 
321
 
            if (newKey)
322
 
                free (newKey);
323
 
 
324
 
            if (!to)
325
 
                gconf_engine_remove_dir (conf, path, NULL);
326
 
        }
327
 
 
328
 
        g_free (path);
329
 
        tmp = g_slist_next (tmp);
330
 
    }
331
 
 
332
 
    if (subdirs)
333
 
        g_slist_free (subdirs);
334
 
}
335
 
 
336
 
static void
337
 
copyGconfTree (CCSBackend  *backend,
338
 
               CCSContext  *context,
339
 
               const gchar *from,
340
 
               const gchar *to,
341
 
               Bool        associate,
342
 
               const gchar *schemaPath)
343
 
{
344
 
    GSList* subdirs;
345
 
 
346
 
    /* we aren't allowed to have an open GConfClient object while
347
 
       using GConfEngine, so shut it down and open it again afterwards */
348
 
    finiClient ();
349
 
 
350
 
    subdirs = gconf_engine_all_dirs (conf, from, NULL);
351
 
    gconf_engine_suggest_sync (conf, NULL);
352
 
 
353
 
    copyGconfRecursively (conf, subdirs, to, associate, schemaPath);
354
 
 
355
 
    gconf_engine_suggest_sync (conf, NULL);
356
 
 
357
 
    initClient (backend, context);
358
 
}
359
 
 
360
 
static Bool
361
 
readListValue (CCSSetting *setting,
362
 
               GConfValue *gconfValue)
363
 
{
364
 
    GConfValueType      valueType;
365
 
    unsigned int        nItems, i = 0;
366
 
    CCSSettingValueList list = NULL;
367
 
    GSList              *valueList = NULL;
368
 
 
369
 
    switch (ccsSettingGetInfo (setting)->forList.listType)
370
 
    {
371
 
    case TypeString:
372
 
    case TypeMatch:
373
 
    case TypeColor:
374
 
        valueType = GCONF_VALUE_STRING;
375
 
        break;
376
 
    case TypeBool:
377
 
        valueType = GCONF_VALUE_BOOL;
378
 
        break;
379
 
    case TypeInt:
380
 
        valueType = GCONF_VALUE_INT;
381
 
        break;
382
 
    case TypeFloat:
383
 
        valueType = GCONF_VALUE_FLOAT;
384
 
        break;
385
 
    default:
386
 
        valueType = GCONF_VALUE_INVALID;
387
 
        break;
388
 
    }
389
 
 
390
 
    if (valueType == GCONF_VALUE_INVALID)
391
 
        return FALSE;
392
 
 
393
 
    if (valueType != gconf_value_get_list_type (gconfValue))
394
 
        return FALSE;
395
 
 
396
 
    valueList = gconf_value_get_list (gconfValue);
397
 
    if (!valueList)
398
 
    {
399
 
        ccsSetList (setting, NULL, TRUE);
400
 
        return TRUE;
401
 
    }
402
 
 
403
 
    nItems = g_slist_length (valueList);
404
 
 
405
 
    switch (ccsSettingGetInfo (setting)->forList.listType)
406
 
    {
407
 
    case TypeBool:
408
 
        {
409
 
            Bool *array = malloc (nItems * sizeof (Bool));
410
 
            if (!array)
411
 
                break;
412
 
 
413
 
            for (; valueList; valueList = valueList->next, ++i)
414
 
                array[i] =
415
 
                    gconf_value_get_bool (valueList->data) ? TRUE : FALSE;
416
 
            list = ccsGetValueListFromBoolArray (array, nItems, setting);
417
 
            free (array);
418
 
        }
419
 
        break;
420
 
    case TypeInt:
421
 
        {
422
 
            int *array = malloc (nItems * sizeof (int));
423
 
            if (!array)
424
 
                break;
425
 
 
426
 
            for (; valueList; valueList = valueList->next, ++i)
427
 
                array[i] = gconf_value_get_int (valueList->data);
428
 
            list = ccsGetValueListFromIntArray (array, nItems, setting);
429
 
            free (array);
430
 
        }
431
 
        break;
432
 
    case TypeFloat:
433
 
        {
434
 
            float *array = malloc (nItems * sizeof (float));
435
 
            if (!array)
436
 
                break;
437
 
 
438
 
            for (; valueList; valueList = valueList->next, ++i)
439
 
                array[i] = gconf_value_get_float (valueList->data);
440
 
            list = ccsGetValueListFromFloatArray (array, nItems, setting);
441
 
            free (array);
442
 
        }
443
 
        break;
444
 
    case TypeString:
445
 
    case TypeMatch:
446
 
        {
447
 
            gchar **array = malloc ((nItems + 1) * sizeof (char*));
448
 
            if (!array)
449
 
                break;
450
 
 
451
 
            for (; valueList; valueList = valueList->next, ++i)
452
 
                array[i] = strdup (gconf_value_get_string (valueList->data));
453
 
 
454
 
            array[nItems] = NULL;
455
 
 
456
 
            list = ccsGetValueListFromStringArray ((const char **) array, nItems, setting);
457
 
            g_strfreev (array);
458
 
        }
459
 
        break;
460
 
    case TypeColor:
461
 
        {
462
 
            CCSSettingColorValue *array;
463
 
            array = malloc (nItems * sizeof (CCSSettingColorValue));
464
 
            if (!array)
465
 
                break;
466
 
 
467
 
            for (; valueList; valueList = valueList->next, ++i)
468
 
            {
469
 
                memset (&array[i], 0, sizeof (CCSSettingColorValue));
470
 
                ccsStringToColor (gconf_value_get_string (valueList->data),
471
 
                                  &array[i]);
472
 
            }
473
 
            list = ccsGetValueListFromColorArray (array, nItems, setting);
474
 
            free (array);
475
 
        }
476
 
        break;
477
 
    default:
478
 
        break;
479
 
    }
480
 
 
481
 
    if (list)
482
 
    {
483
 
        ccsSetList (setting, list, TRUE);
484
 
        ccsSettingValueListFree (list, TRUE);
485
 
        return TRUE;
486
 
    }
487
 
 
488
 
    return FALSE;
489
 
}
490
 
 
491
 
 
492
 
static Bool
493
 
readIntegratedOption (CCSContext *context,
494
 
                      CCSSetting *setting,
495
 
                      CCSIntegratedSetting *integrated)
496
 
{
497
 
    return ccsIntegrationReadOptionIntoSetting (valueChangeData.integration, context, setting, integrated);
498
 
}
499
 
 
500
 
static Bool
501
 
readOption (CCSSetting * setting)
502
 
{
503
 
    GConfValue *gconfValue = NULL;
504
 
    GError     *err = NULL;
505
 
    Bool       ret = FALSE;
506
 
    Bool       valid = TRUE;
507
 
 
508
 
    KEYNAME (ccsContextGetScreenNum (ccsPluginGetContext (ccsSettingGetParent (setting))));
509
 
    PATHNAME;
510
 
 
511
 
    /* first check if the key is set */
512
 
    gconfValue = gconf_client_get_without_default (client, pathName, &err);
513
 
    if (err)
514
 
    {
515
 
        g_error_free (err);
516
 
        return FALSE;
517
 
    }
518
 
    if (!gconfValue)
519
 
        /* value is not set */
520
 
        return FALSE;
521
 
 
522
 
    /* setting type sanity check */
523
 
    switch (ccsSettingGetType (setting))
524
 
    {
525
 
    case TypeString:
526
 
    case TypeMatch:
527
 
    case TypeColor:
528
 
    case TypeKey:
529
 
    case TypeButton:
530
 
    case TypeEdge:
531
 
        valid = (gconfValue->type == GCONF_VALUE_STRING);
532
 
        break;
533
 
    case TypeInt:
534
 
        valid = (gconfValue->type == GCONF_VALUE_INT);
535
 
        break;
536
 
    case TypeBool:
537
 
    case TypeBell:
538
 
        valid = (gconfValue->type == GCONF_VALUE_BOOL);
539
 
        break;
540
 
    case TypeFloat:
541
 
        valid = (gconfValue->type == GCONF_VALUE_FLOAT);
542
 
        break;
543
 
    case TypeList:
544
 
        valid = (gconfValue->type == GCONF_VALUE_LIST);
545
 
        break;
546
 
    default:
547
 
        break;
548
 
    }
549
 
    if (!valid)
550
 
    {
551
 
        ccsWarning ("There is an unsupported value at path %s. "
552
 
                "Settings from this path won't be read. Try to remove "
553
 
                "that value so that operation can continue properly.",
554
 
                pathName);
555
 
        return FALSE;
556
 
    }
557
 
 
558
 
    switch (ccsSettingGetType (setting))
559
 
    {
560
 
    case TypeString:
561
 
        {
562
 
            const char *value;
563
 
            value = gconf_value_get_string (gconfValue);
564
 
            if (value)
565
 
            {
566
 
                ccsSetString (setting, value, TRUE);
567
 
                ret = TRUE;
568
 
            }
569
 
        }
570
 
        break;
571
 
    case TypeMatch:
572
 
        {
573
 
            const char * value;
574
 
            value = gconf_value_get_string (gconfValue);
575
 
            if (value)
576
 
            {
577
 
                ccsSetMatch (setting, value, TRUE);
578
 
                ret = TRUE;
579
 
            }
580
 
        }
581
 
        break;
582
 
    case TypeInt:
583
 
        {
584
 
            int value;
585
 
            value = gconf_value_get_int (gconfValue);
586
 
 
587
 
            ccsSetInt (setting, value, TRUE);
588
 
            ret = TRUE;
589
 
        }
590
 
        break;
591
 
    case TypeBool:
592
 
        {
593
 
            gboolean value;
594
 
            value = gconf_value_get_bool (gconfValue);
595
 
 
596
 
            ccsSetBool (setting, value ? TRUE : FALSE, TRUE);
597
 
            ret = TRUE;
598
 
        }
599
 
        break;
600
 
    case TypeFloat:
601
 
        {
602
 
            double value;
603
 
            value = gconf_value_get_float (gconfValue);
604
 
 
605
 
            ccsSetFloat (setting, (float)value, TRUE);
606
 
            ret = TRUE;
607
 
        }
608
 
        break;
609
 
    case TypeColor:
610
 
        {
611
 
            const char           *value;
612
 
            CCSSettingColorValue color;
613
 
            value = gconf_value_get_string (gconfValue);
614
 
 
615
 
            if (value && ccsStringToColor (value, &color))
616
 
            {
617
 
                ccsSetColor (setting, color, TRUE);
618
 
                ret = TRUE;
619
 
            }
620
 
        }
621
 
        break;
622
 
    case TypeKey:
623
 
        {
624
 
            const char         *value;
625
 
            CCSSettingKeyValue key;
626
 
            value = gconf_value_get_string (gconfValue);
627
 
 
628
 
            if (value && ccsStringToKeyBinding (value, &key))
629
 
            {
630
 
                ccsSetKey (setting, key, TRUE);
631
 
                ret = TRUE;
632
 
            }
633
 
        }
634
 
        break;
635
 
    case TypeButton:
636
 
        {
637
 
            const char            *value;
638
 
            CCSSettingButtonValue button;
639
 
            value = gconf_value_get_string (gconfValue);
640
 
 
641
 
            if (value && ccsStringToButtonBinding (value, &button))
642
 
            {
643
 
                ccsSetButton (setting, button, TRUE);
644
 
                ret = TRUE;
645
 
            }
646
 
        }
647
 
        break;
648
 
    case TypeEdge:
649
 
        {
650
 
            const char   *value;
651
 
            value = gconf_value_get_string (gconfValue);
652
 
 
653
 
            if (value)
654
 
            {
655
 
                unsigned int edges;
656
 
                edges = ccsStringToEdges (value);
657
 
                ccsSetEdge (setting, edges, TRUE);
658
 
                ret = TRUE;
659
 
            }
660
 
        }
661
 
        break;
662
 
    case TypeBell:
663
 
        {
664
 
            gboolean value;
665
 
            value = gconf_value_get_bool (gconfValue);
666
 
 
667
 
            ccsSetBell (setting, value ? TRUE : FALSE, TRUE);
668
 
            ret = TRUE;
669
 
        }
670
 
        break;
671
 
    case TypeList:
672
 
        ret = readListValue (setting, gconfValue);
673
 
        break;
674
 
    default:
675
 
        ccsWarning ("Attempt to read unsupported setting type %d from path %s!",
676
 
               ccsSettingGetType (setting), pathName);
677
 
        break;
678
 
    }
679
 
 
680
 
    if (gconfValue)
681
 
        gconf_value_free (gconfValue);
682
 
 
683
 
    return ret;
684
 
}
685
 
 
686
 
static void
687
 
writeListValue (CCSSetting *setting,
688
 
                char       *pathName)
689
 
{
690
 
    GSList              *valueList = NULL;
691
 
    GConfValueType      valueType;
692
 
    Bool                freeItems = FALSE;
693
 
    CCSSettingValueList list;
694
 
    gpointer            data;
695
 
 
696
 
    if (!ccsGetList (setting, &list))
697
 
        return;
698
 
 
699
 
    switch (ccsSettingGetInfo (setting)->forList.listType)
700
 
    {
701
 
    case TypeBool:
702
 
        {
703
 
            while (list)
704
 
            {
705
 
                data = GINT_TO_POINTER (list->data->value.asBool);
706
 
                valueList = g_slist_append (valueList, data);
707
 
                list = list->next;
708
 
            }
709
 
            valueType = GCONF_VALUE_BOOL;
710
 
        }
711
 
        break;
712
 
    case TypeInt:
713
 
        {
714
 
            while (list)
715
 
            {
716
 
                data = GINT_TO_POINTER (list->data->value.asInt);
717
 
                valueList = g_slist_append(valueList, data);
718
 
                list = list->next;
719
 
            }
720
 
            valueType = GCONF_VALUE_INT;
721
 
        }
722
 
        break;
723
 
    case TypeFloat:
724
 
        {
725
 
            gdouble *item;
726
 
            while (list)
727
 
            {
728
 
                item = malloc (sizeof (gdouble));
729
 
                if (item)
730
 
                {
731
 
                    *item = list->data->value.asFloat;
732
 
                    valueList = g_slist_append (valueList, item);
733
 
                }
734
 
                list = list->next;
735
 
            }
736
 
            freeItems = TRUE;
737
 
            valueType = GCONF_VALUE_FLOAT;
738
 
        }
739
 
        break;
740
 
    case TypeString:
741
 
        {
742
 
            while (list)
743
 
            {
744
 
                valueList = g_slist_append(valueList,
745
 
                                           list->data->value.asString);
746
 
                list = list->next;
747
 
            }
748
 
            valueType = GCONF_VALUE_STRING;
749
 
        }
750
 
        break;
751
 
    case TypeMatch:
752
 
        {
753
 
            while (list)
754
 
            {
755
 
                valueList = g_slist_append(valueList,
756
 
                                           list->data->value.asMatch);
757
 
                list = list->next;
758
 
            }
759
 
            valueType = GCONF_VALUE_STRING;
760
 
        }
761
 
        break;
762
 
    case TypeColor:
763
 
        {
764
 
            char *item;
765
 
            while (list)
766
 
            {
767
 
                item = ccsColorToString (&list->data->value.asColor);
768
 
                valueList = g_slist_append (valueList, item);
769
 
                list = list->next;
770
 
            }
771
 
            freeItems = TRUE;
772
 
            valueType = GCONF_VALUE_STRING;
773
 
        }
774
 
        break;
775
 
    default:
776
 
        ccsWarning ("Attempt to write unsupported list type %d at path %s!",
777
 
               ccsSettingGetInfo (setting)->forList.listType, pathName);
778
 
        valueType = GCONF_VALUE_INVALID;
779
 
        break;
780
 
    }
781
 
 
782
 
    if (valueType != GCONF_VALUE_INVALID)
783
 
    {
784
 
        gconf_client_set_list (client, pathName, valueType, valueList, NULL);
785
 
 
786
 
        if (freeItems)
787
 
        {
788
 
            GSList *tmpList = valueList;
789
 
            for (; tmpList; tmpList = tmpList->next)
790
 
                if (tmpList->data)
791
 
                    free (tmpList->data);
792
 
        }
793
 
    }
794
 
    if (valueList)
795
 
        g_slist_free (valueList);
796
 
}
797
 
 
798
 
static void
799
 
writeIntegratedOption (CCSContext *context,
800
 
                       CCSSetting *setting,
801
 
                       CCSIntegratedSetting *integrated)
802
 
{
803
 
    ccsIntegrationWriteSettingIntoOption (valueChangeData.integration, context, setting, integrated);
804
 
}
805
 
 
806
 
static void
807
 
resetOptionToDefault (CCSSetting * setting)
808
 
{
809
 
    KEYNAME (ccsContextGetScreenNum (ccsPluginGetContext (ccsSettingGetParent (setting))));
810
 
    PATHNAME;
811
 
 
812
 
    gconf_client_recursive_unset (client, pathName, 0, NULL);
813
 
    gconf_client_suggest_sync (client, NULL);
814
 
}
815
 
 
816
 
static void
817
 
writeOption (CCSSetting * setting)
818
 
{
819
 
    KEYNAME (ccsContextGetScreenNum (ccsPluginGetContext (ccsSettingGetParent (setting))));
820
 
    PATHNAME;
821
 
 
822
 
    switch (ccsSettingGetType (setting))
823
 
    {
824
 
    case TypeString:
825
 
        {
826
 
            const char *value;
827
 
            if (ccsGetString (setting, &value))
828
 
                gconf_client_set_string (client, pathName, value, NULL);
829
 
        }
830
 
        break;
831
 
    case TypeMatch:
832
 
        {
833
 
            const char *value;
834
 
            if (ccsGetMatch (setting, &value))
835
 
                gconf_client_set_string (client, pathName, value, NULL);
836
 
        }
837
 
    case TypeFloat:
838
 
        {
839
 
            float value;
840
 
            if (ccsGetFloat (setting, &value))
841
 
                gconf_client_set_float (client, pathName, value, NULL);
842
 
        }
843
 
        break;
844
 
    case TypeInt:
845
 
        {
846
 
            int value;
847
 
            if (ccsGetInt (setting, &value))
848
 
                gconf_client_set_int (client, pathName, value, NULL);
849
 
        }
850
 
        break;
851
 
    case TypeBool:
852
 
        {
853
 
            Bool value;
854
 
            if (ccsGetBool (setting, &value))
855
 
                gconf_client_set_bool (client, pathName, value, NULL);
856
 
        }
857
 
        break;
858
 
    case TypeColor:
859
 
        {
860
 
            CCSSettingColorValue value;
861
 
            char                 *colString;
862
 
 
863
 
            if (!ccsGetColor (setting, &value))
864
 
                break;
865
 
 
866
 
            colString = ccsColorToString (&value);
867
 
            if (!colString)
868
 
                break;
869
 
 
870
 
            gconf_client_set_string (client, pathName, colString, NULL);
871
 
            free (colString);
872
 
        }
873
 
        break;
874
 
    case TypeKey:
875
 
        {
876
 
            CCSSettingKeyValue key;
877
 
            char               *keyString;
878
 
 
879
 
            if (!ccsGetKey (setting, &key))
880
 
                break;
881
 
 
882
 
            keyString = ccsKeyBindingToString (&key);
883
 
            if (!keyString)
884
 
                break;
885
 
 
886
 
            gconf_client_set_string (client, pathName, keyString, NULL);
887
 
            free (keyString);
888
 
        }
889
 
        break;
890
 
    case TypeButton:
891
 
        {
892
 
            CCSSettingButtonValue button;
893
 
            char                  *buttonString;
894
 
 
895
 
            if (!ccsGetButton (setting, &button))
896
 
                break;
897
 
 
898
 
            buttonString = ccsButtonBindingToString (&button);
899
 
            if (!buttonString)
900
 
                break;
901
 
 
902
 
            gconf_client_set_string (client, pathName, buttonString, NULL);
903
 
            free (buttonString);
904
 
        }
905
 
        break;
906
 
    case TypeEdge:
907
 
        {
908
 
            unsigned int edges;
909
 
            char         *edgeString;
910
 
 
911
 
            if (!ccsGetEdge (setting, &edges))
912
 
                break;
913
 
 
914
 
            edgeString = ccsEdgesToString (edges);
915
 
            if (!edgeString)
916
 
                break;
917
 
 
918
 
            gconf_client_set_string (client, pathName, edgeString, NULL);
919
 
            free (edgeString);
920
 
        }
921
 
        break;
922
 
    case TypeBell:
923
 
        {
924
 
            Bool value;
925
 
            if (ccsGetBell (setting, &value))
926
 
                gconf_client_set_bool (client, pathName, value, NULL);
927
 
        }
928
 
        break;
929
 
    case TypeList:
930
 
        writeListValue (setting, pathName);
931
 
        break;
932
 
    default:
933
 
        ccsWarning ("Attempt to write unsupported setting type %d",
934
 
               ccsSettingGetType (setting));
935
 
        break;
936
 
    }
937
 
}
938
 
 
939
 
static void
940
 
updateCurrentProfileName (char *profile)
941
 
{
942
 
    GConfSchema *schema;
943
 
    GConfValue  *value;
944
 
    
945
 
    schema = gconf_schema_new ();
946
 
    if (!schema)
947
 
        return;
948
 
 
949
 
    value = gconf_value_new (GCONF_VALUE_STRING);
950
 
    if (!value)
951
 
    {
952
 
        gconf_schema_free (schema);
953
 
        return;
954
 
    }
955
 
 
956
 
    gconf_schema_set_type (schema, GCONF_VALUE_STRING);
957
 
    gconf_schema_set_locale (schema, "C");
958
 
    gconf_schema_set_short_desc (schema, "Current profile");
959
 
    gconf_schema_set_long_desc (schema, "Current profile of gconf backend");
960
 
    gconf_schema_set_owner (schema, "compizconfig-1");
961
 
    gconf_value_set_string (value, profile);
962
 
    gconf_schema_set_default_value (schema, value);
963
 
 
964
 
    gconf_client_set_schema (client, COMPIZCONFIG "/current_profile",
965
 
                             schema, NULL);
966
 
 
967
 
    gconf_schema_free (schema);
968
 
    gconf_value_free (value);
969
 
}
970
 
 
971
 
static char*
972
 
getCurrentProfileName (void)
973
 
{
974
 
    GConfSchema *schema = NULL;
975
 
 
976
 
    schema = gconf_client_get_schema (client,
977
 
                                      COMPIZCONFIG "/current_profile", NULL);
978
 
 
979
 
    if (schema)
980
 
    {
981
 
        GConfValue *value;
982
 
        char       *ret = NULL;
983
 
 
984
 
        value = gconf_schema_get_default_value (schema);
985
 
        if (value)
986
 
            ret = strdup (gconf_value_get_string (value));
987
 
        gconf_schema_free (schema);
988
 
 
989
 
        return ret;
990
 
    }
991
 
 
992
 
    return NULL;
993
 
}
994
 
 
995
 
static Bool
996
 
checkProfile (CCSBackend *backend,
997
 
              CCSContext *context)
998
 
{
999
 
    const char *profileCCS;
1000
 
    char *lastProfile;
1001
 
 
1002
 
    lastProfile = currentProfile;
1003
 
 
1004
 
    profileCCS = ccsGetProfile (context);
1005
 
    if (!profileCCS || !strlen (profileCCS))
1006
 
        currentProfile = strdup (DEFAULTPROF);
1007
 
    else
1008
 
        currentProfile = strdup (profileCCS);
1009
 
 
1010
 
    if (!lastProfile || strcmp (lastProfile, currentProfile) != 0)
1011
 
    {
1012
 
        char *pathName;
1013
 
 
1014
 
        if (lastProfile)
1015
 
        {
1016
 
            /* copy /apps/compiz-1 tree to profile path */
1017
 
            if (asprintf (&pathName, "%s/%s", PROFILEPATH, lastProfile) == -1)
1018
 
                pathName = NULL;
1019
 
 
1020
 
            if (pathName)
1021
 
            {
1022
 
                copyGconfTree (backend,
1023
 
                               context, COMPIZ, pathName,
1024
 
                               TRUE, "/schemas" COMPIZ);
1025
 
                free (pathName);
1026
 
            }
1027
 
        }
1028
 
 
1029
 
        /* reset /apps/compiz-1 tree */
1030
 
        gconf_client_recursive_unset (client, COMPIZ, 0, NULL);
1031
 
 
1032
 
        /* copy new profile tree to /apps/compiz-1 */
1033
 
        if (asprintf (&pathName, "%s/%s", PROFILEPATH, currentProfile) == -1)
1034
 
            pathName = NULL;
1035
 
 
1036
 
        if (pathName)
1037
 
        {
1038
 
            copyGconfTree (backend, context, pathName, COMPIZ, FALSE, NULL);
1039
 
 
1040
 
            /* delete the new profile tree in /apps/compizconfig-1
1041
 
               to avoid user modification in the wrong tree */
1042
 
            copyGconfTree (backend, context, pathName, NULL, TRUE, NULL);
1043
 
            free (pathName);
1044
 
        }
1045
 
 
1046
 
        /* update current profile name */
1047
 
        updateCurrentProfileName (currentProfile);
1048
 
    }
1049
 
 
1050
 
    if (lastProfile)
1051
 
        free (lastProfile);
1052
 
 
1053
 
    return TRUE;
1054
 
}
1055
 
 
1056
 
static void
1057
 
processEvents (CCSBackend *backend, unsigned int flags)
1058
 
{
1059
 
    if (!(flags & ProcessEventsNoGlibMainLoopMask))
1060
 
    {
1061
 
        while (g_main_context_pending(NULL))
1062
 
            g_main_context_iteration(NULL, FALSE);
1063
 
    }
1064
 
}
1065
 
 
1066
 
static Bool
1067
 
initBackend (CCSBackend *backend, CCSContext * context)
1068
 
{
1069
 
    g_type_init ();
1070
 
 
1071
 
    conf = gconf_engine_get_default ();
1072
 
    initClient (backend, context);
1073
 
 
1074
 
    currentProfile = getCurrentProfileName ();
1075
 
 
1076
 
    return TRUE;
1077
 
}
1078
 
 
1079
 
static Bool
1080
 
finiBackend (CCSBackend *backend)
1081
 
{
1082
 
    gconf_client_clear_cache (client);
1083
 
    finiClient ();
1084
 
 
1085
 
    if (currentProfile)
1086
 
    {
1087
 
        free (currentProfile);
1088
 
        currentProfile = NULL;
1089
 
    }
1090
 
 
1091
 
    gconf_engine_unref (conf);
1092
 
    conf = NULL;
1093
 
 
1094
 
    return TRUE;
1095
 
}
1096
 
 
1097
 
static Bool
1098
 
readInit (CCSBackend *backend, CCSContext * context)
1099
 
{
1100
 
    return checkProfile (backend, context);
1101
 
}
1102
 
 
1103
 
static void
1104
 
readSetting (CCSBackend *backend,
1105
 
             CCSContext *context,
1106
 
             CCSSetting *setting)
1107
 
{
1108
 
    Bool status;
1109
 
    CCSIntegratedSetting *integrated;
1110
 
 
1111
 
    if (ccsGetIntegrationEnabled (context) &&
1112
 
        isIntegratedOption (setting, &integrated))
1113
 
    {
1114
 
        status = readIntegratedOption (context, setting, integrated);
1115
 
    }
1116
 
    else
1117
 
        status = readOption (setting);
1118
 
 
1119
 
    if (!status)
1120
 
        ccsResetToDefault (setting, TRUE);
1121
 
}
1122
 
 
1123
 
static Bool
1124
 
writeInit (CCSBackend *backend, CCSContext * context)
1125
 
{
1126
 
    return checkProfile (backend, context);
1127
 
}
1128
 
 
1129
 
static void
1130
 
writeSetting (CCSBackend *backend,
1131
 
              CCSContext *context,
1132
 
              CCSSetting *setting)
1133
 
{
1134
 
    CCSIntegratedSetting *integrated;
1135
 
 
1136
 
    if (ccsGetIntegrationEnabled (context) &&
1137
 
        isIntegratedOption (setting, &integrated))
1138
 
    {
1139
 
        writeIntegratedOption (context, setting, integrated);
1140
 
    }
1141
 
    else if (ccsSettingGetIsDefault (setting))
1142
 
    {
1143
 
        resetOptionToDefault (setting);
1144
 
    }
1145
 
    else
1146
 
        writeOption (setting);
1147
 
 
1148
 
}
1149
 
 
1150
 
static Bool
1151
 
getSettingIsIntegrated (CCSBackend *backend, CCSSetting * setting)
1152
 
{
1153
 
    if (!ccsGetIntegrationEnabled (ccsPluginGetContext (ccsSettingGetParent (setting))))
1154
 
        return FALSE;
1155
 
 
1156
 
    if (!isIntegratedOption (setting, NULL))
1157
 
        return FALSE;
1158
 
 
1159
 
    return TRUE;
1160
 
}
1161
 
 
1162
 
static Bool
1163
 
getSettingIsReadOnly (CCSBackend *backend, CCSSetting * setting)
1164
 
{
1165
 
    /* FIXME */
1166
 
    return FALSE;
1167
 
}
1168
 
 
1169
 
static CCSStringList
1170
 
getExistingProfiles (CCSBackend *backend, CCSContext *context)
1171
 
{
1172
 
    GSList        *data, *tmp;
1173
 
    CCSStringList ret = NULL;
1174
 
    char          *name;
1175
 
 
1176
 
    gconf_client_suggest_sync (client, NULL);
1177
 
    data = gconf_client_all_dirs (client, PROFILEPATH, NULL);
1178
 
 
1179
 
    for (tmp = data; tmp; tmp = g_slist_next (tmp))
1180
 
    {
1181
 
        name = strrchr (tmp->data, '/');
1182
 
        if (name && (strcmp (name + 1, DEFAULTPROF) != 0))
1183
 
        {
1184
 
            CCSString *str = calloc (1, sizeof (CCSString));
1185
 
            str->value = strdup (name + 1);
1186
 
            ret = ccsStringListAppend (ret, str);
1187
 
        }
1188
 
 
1189
 
        g_free (tmp->data);
1190
 
    }
1191
 
 
1192
 
    g_slist_free (data);
1193
 
 
1194
 
    name = getCurrentProfileName ();
1195
 
    if (name && strcmp (name, DEFAULTPROF) != 0)
1196
 
    {
1197
 
        CCSString *str = calloc (1, sizeof (CCSString));
1198
 
        str->value = name;
1199
 
        ret = ccsStringListAppend (ret, str);
1200
 
    }
1201
 
    else if (name)
1202
 
        free (name);
1203
 
 
1204
 
    return ret;
1205
 
}
1206
 
 
1207
 
static Bool
1208
 
deleteProfile (CCSBackend *backend,
1209
 
               CCSContext *context,
1210
 
               char       *profile)
1211
 
{
1212
 
    char     path[BUFSIZE];
1213
 
    gboolean status = FALSE;
1214
 
 
1215
 
    checkProfile (backend, context);
1216
 
 
1217
 
    snprintf (path, BUFSIZE, "%s/%s", PROFILEPATH, profile);
1218
 
 
1219
 
    if (gconf_client_dir_exists (client, path, NULL))
1220
 
    {
1221
 
        status =
1222
 
            gconf_client_recursive_unset (client, path,
1223
 
                                          GCONF_UNSET_INCLUDING_SCHEMA_NAMES,
1224
 
                                          NULL);
1225
 
        gconf_client_suggest_sync (client, NULL);
1226
 
    }
1227
 
 
1228
 
    return status;
1229
 
}
1230
 
 
1231
 
const CCSBackendInfo gconfBackendInfo =
1232
 
{
1233
 
    "gconf",
1234
 
    "GConf Configuration Backend",
1235
 
    "GConf Configuration Backend for libccs",
1236
 
    TRUE,
1237
 
    TRUE,
1238
 
    1
1239
 
};
1240
 
 
1241
 
static const CCSBackendInfo *
1242
 
getInfo (CCSBackend *backend)
1243
 
{
1244
 
    return &gconfBackendInfo;
1245
 
}
1246
 
 
1247
 
static CCSBackendInterface gconfVTable = {
1248
 
    getInfo,
1249
 
    processEvents,
1250
 
    initBackend,
1251
 
    finiBackend,
1252
 
    readInit,
1253
 
    readSetting,
1254
 
    0,
1255
 
    writeInit,
1256
 
    writeSetting,
1257
 
    0,
1258
 
    updateSetting,
1259
 
    getSettingIsIntegrated,
1260
 
    getSettingIsReadOnly,
1261
 
    getExistingProfiles,
1262
 
    deleteProfile
1263
 
};
1264
 
 
1265
 
CCSBackendInterface *
1266
 
getBackendInfo (void)
1267
 
{
1268
 
    return &gconfVTable;
1269
 
}
1270