~cairo-dock-team/cairo-dock-session/cairo-dock-session

« back to all changes in this revision

Viewing changes to xsettings/xsettings.c

  • Committer: Fabrice Rey
  • Date: 2011-09-10 00:06:15 UTC
  • Revision ID: fabounet03@gmail.com-20110910000615-ikwipf93g9edjd3h
removed unused files and reordered other files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
* This file is a part of the Cairo-Dock project
 
3
*
 
4
* Copyright : (C) see the 'copyright' file.
 
5
* E-mail    : see the 'copyright' file.
 
6
*
 
7
* This program is free software; you can redistribute it and/or
 
8
* modify it under the terms of the GNU General Public License
 
9
* as published by the Free Software Foundation; either version 3
 
10
* of the License, or (at your option) any later version.
 
11
*
 
12
* This program is distributed in the hope that it will be useful,
 
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
* GNU General Public License for more details.
 
16
* You should have received a copy of the GNU General Public License
 
17
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
// To compil it, run:
 
21
// gcc `pkg-config --cflags --libs glib-2.0 dbus-glib-1 gtk+-2.0` -o xsettings -ggdb xsettings.c
 
22
 
 
23
#include <string.h>
 
24
#include <stdlib.h>
 
25
#include <stdio.h>
 
26
#include <signal.h> 
 
27
#include <unistd.h>
 
28
#include <math.h>  // ceil
 
29
 
 
30
#include <X11/Xlib.h>
 
31
#include <X11/Xatom.h>
 
32
#include <X11/Xutil.h>
 
33
#include <X11/Xmd.h>
 
34
 
 
35
#include <gtk/gtk.h>
 
36
#include <gdk/gdkx.h>
 
37
 
 
38
#include <glib.h>
 
39
#include <dbus/dbus-glib.h>
 
40
#include <dbus/dbus-glib-bindings.h>
 
41
 
 
42
typedef struct {
 
43
        GObject parent;
 
44
} dbusMainObject;
 
45
typedef struct {
 
46
        GObjectClass parent_class;
 
47
} dbusMainObjectClass;
 
48
gboolean xsettings_set (dbusMainObject *pDbusObject, const gchar *cSettingName, GValue *pValue, GError **error);
 
49
 
 
50
#include "xsettings-dbus-spec.h"
 
51
 
 
52
static Display *dpy = NULL;
 
53
static int serial = 1;
 
54
static Atom selection_atom;
 
55
static Atom xsettings_atom;
 
56
static Window window = 0;
 
57
static GHashTable *pSettings = NULL;
 
58
 
 
59
static dbusMainObject *pMainObject = NULL;
 
60
 
 
61
typedef enum {
 
62
        SETTING_INT=0,
 
63
        SETTING_STRING,
 
64
        SETTING_COLOR,
 
65
        NB_SETTING_TYPES
 
66
} SettingType;
 
67
 
 
68
typedef struct {
 
69
        guint type;
 
70
        int iSerial;
 
71
        int iValue;
 
72
        gchar *cValue;
 
73
        short color[4];
 
74
        int value_len;
 
75
        int value_pad;
 
76
        int name_len;
 
77
        int name_pad;
 
78
        int iSize;
 
79
} Setting;
 
80
 
 
81
 
 
82
static int _xerror_handler (Display * pDisplay, XErrorEvent *pXError)
 
83
{
 
84
        g_warning ("Error (%d, %d, %d) during an X request on %ld", pXError->error_code, pXError->request_code, pXError->minor_code, pXError->resourceid);
 
85
        return 0;
 
86
}
 
87
 
 
88
 
 
89
static inline _insert_setting (const gchar *cName, guint iType)
 
90
{
 
91
        Setting *pSetting = g_new0 (Setting, 1);
 
92
        pSetting->type = iType;
 
93
        g_hash_table_insert (pSettings, g_strdup (cName), pSetting);
 
94
}
 
95
 
 
96
static void register_settings (void)
 
97
{
 
98
        pSettings = g_hash_table_new (g_str_hash,
 
99
                g_str_equal);
 
100
        
 
101
        _insert_setting ("Net/ThemeName",                               G_TYPE_STRING);
 
102
        _insert_setting ("Net/IconThemeName",                   G_TYPE_STRING);
 
103
        _insert_setting ("Net/SoundThemeName",                  G_TYPE_STRING);
 
104
        _insert_setting ("Net/EnableEventSounds",               G_TYPE_BOOLEAN);
 
105
        _insert_setting ("Net/EnableInputFeedbackSounds",       G_TYPE_BOOLEAN);
 
106
        _insert_setting ("Gtk/FontName",                                G_TYPE_STRING);
 
107
        _insert_setting ("Gtk/CursorThemeName",                         G_TYPE_STRING);
 
108
}
 
109
 
 
110
 
 
111
  //////////////////
 
112
 /// X SETTINGS ///
 
113
//////////////////
 
114
 
 
115
#define pad(n) ((4 - ((n)%4)) % 4)
 
116
static void _compute_buffer_size (const gchar *cName, Setting *pSetting, int *data)
 
117
{
 
118
        if (pSetting->iSerial == 0)  // ignore settings that have never been defined.
 
119
                return;
 
120
        
 
121
        g_print ("%s (%s)\n", __func__, cName);
 
122
        pSetting->iSize = 1 + 1 + 2 + 4;  // type + unused + name_len + serial
 
123
        int value_len, value_pad;
 
124
        switch (pSetting->type)
 
125
        {
 
126
                case G_TYPE_BOOLEAN:
 
127
                case G_TYPE_INT:
 
128
                        value_len = 4;
 
129
                        value_pad = 0;
 
130
                break;
 
131
                case G_TYPE_STRING:
 
132
                        if (pSetting->cValue == NULL)
 
133
                                return;
 
134
                        value_len = strlen (pSetting->cValue);
 
135
                        value_pad = pad (value_len);
 
136
                        pSetting->iSize += 4;  // for value_len
 
137
                break;
 
138
                case G_TYPE_UINT64:
 
139
                        value_len = 8;  // 4 shorts.
 
140
                        value_pad = 0;
 
141
                break;
 
142
                default:
 
143
                return;
 
144
        }
 
145
        pSetting->value_len = value_len;
 
146
        pSetting->value_pad = value_pad;
 
147
        pSetting->iSize += value_len + value_pad;
 
148
        
 
149
        int name_len = strlen (cName);
 
150
        int name_pad = pad (name_len);
 
151
        pSetting->name_len = name_len;
 
152
        pSetting->name_pad = name_pad;
 
153
        
 
154
        pSetting->iSize += name_len + name_pad;
 
155
        data[0] ++;
 
156
        data[1] += pSetting->iSize;
 
157
        g_print (" %d / %d / %d\n", pSetting->name_len+pSetting->name_pad, pSetting->value_len+pSetting->value_pad, pSetting->iSize);
 
158
}
 
159
 
 
160
static void _build_buffer (const gchar *cName, Setting *pSetting, guchar **data)
 
161
{
 
162
        if (pSetting->iSerial == 0)  // ignore settings that have never been defined.
 
163
                return;
 
164
        guchar *buf = *data;
 
165
        
 
166
        // type
 
167
        switch (pSetting->type)
 
168
        {
 
169
                case G_TYPE_BOOLEAN:
 
170
                case G_TYPE_INT:
 
171
                        *buf = SETTING_INT;
 
172
                break;
 
173
                case G_TYPE_STRING:
 
174
                        *buf = SETTING_STRING;
 
175
                break;
 
176
                case G_TYPE_UINT64:
 
177
                        *buf = SETTING_COLOR;
 
178
                break;
 
179
                default:
 
180
                return;
 
181
        }
 
182
        buf += 1;
 
183
        // unused
 
184
        buf += 1;
 
185
        // name_len
 
186
        *(CARD16*)buf = pSetting->name_len;
 
187
        buf += 2;
 
188
        // name
 
189
        memcpy (buf, cName, pSetting->name_len);
 
190
        buf += pSetting->name_len + pSetting->name_pad;
 
191
        // last_change_serial
 
192
        *(CARD32*)buf = pSetting->iSerial;
 
193
        buf += 4;
 
194
        // value
 
195
        switch (pSetting->type)
 
196
        {
 
197
                case G_TYPE_BOOLEAN:
 
198
                case G_TYPE_INT:
 
199
                        *(CARD32*)buf = pSetting->iValue;
 
200
                break;
 
201
                case G_TYPE_STRING:
 
202
                        // value_len
 
203
                        *(CARD32*)buf = pSetting->value_len;
 
204
                        buf += 4;
 
205
                        memcpy (buf, pSetting->cValue, pSetting->value_len);
 
206
                break;
 
207
                case G_TYPE_UINT64:
 
208
                {
 
209
                        int i;
 
210
                        for (i = 0; i < 4; i ++)
 
211
                        {
 
212
                                ((CARD16*)buf)[i] = pSetting->color[i];
 
213
                        }
 
214
                }
 
215
                break;
 
216
                default:
 
217
                return;
 
218
        }
 
219
        buf += pSetting->value_len + pSetting->value_pad;
 
220
        
 
221
        *data = buf;
 
222
}
 
223
 
 
224
static void _update_settings_on_X (void)
 
225
{
 
226
        // compute the buffer size for the settings that have been defined.
 
227
        int data[2] = {0, 0};  // nb settings, buffer size.
 
228
        data[1] = 12;  // header
 
229
        g_hash_table_foreach (pSettings, (GHFunc)_compute_buffer_size, data);
 
230
        int iNbSettings = data[0];
 
231
        int iSize = data[1];
 
232
        g_print (" nb settings: %d; iSize: %d\n", iNbSettings, iSize);
 
233
        g_return_if_fail (iSize != 0);
 
234
        
 
235
        // build the buffer to send to X.
 
236
        guchar *buffer = g_new0 (gchar, iSize);
 
237
        guchar *pos = buffer;
 
238
        // byte-order
 
239
        #if G_BYTE_ORDER == G_LITTLE_ENDIAN
 
240
        *pos = LSBFirst;
 
241
        #else
 
242
        *pos = MSBFirst;
 
243
        #endif
 
244
        pos += 1;
 
245
        // unused
 
246
        pos += 3;
 
247
        // serial
 
248
        *(CARD32 *)pos = serial;
 
249
        pos += 4;
 
250
        // n_settings
 
251
        *(CARD32 *)pos = iNbSettings;
 
252
        pos += 4;
 
253
        // settings
 
254
        g_hash_table_foreach (pSettings, (GHFunc)_build_buffer, &pos);
 
255
        g_print (" %d/%d bytes filled\n", pos - buffer, iSize);
 
256
                        
 
257
        // now set these settings on our window.
 
258
        XChangeProperty (dpy,
 
259
                window,
 
260
                xsettings_atom,
 
261
                xsettings_atom,
 
262
                8, PropModeReplace, buffer, iSize);
 
263
        g_free (buffer);
 
264
        serial ++;
 
265
}
 
266
 
 
267
 
 
268
  ////////////////////////
 
269
 /// SETTINGS STORAGE ///
 
270
////////////////////////
 
271
 
 
272
static void _store_setting (const gchar *cSettingName, Setting *pSetting)
 
273
{
 
274
        gchar *cConfFilePath = g_strdup_printf ("%s/.config/xsettings.conf", g_getenv ("HOME"));
 
275
        GKeyFile *pKeyFile = g_key_file_new ();
 
276
        GError *error = NULL;
 
277
        g_key_file_load_from_file (pKeyFile, cConfFilePath, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error);
 
278
        if (error != NULL)
 
279
        {
 
280
                g_warning ("couldn't parse %s : %s", cConfFilePath, error->message);
 
281
                g_error_free (error);
 
282
                return ;
 
283
        }
 
284
        
 
285
        gchar *str = strchr (cSettingName, '/');
 
286
        if (!str)
 
287
                return ;
 
288
        *str = '\0';
 
289
        const gchar *cGroupName = cSettingName;
 
290
        const gchar *cKeyName = str + 1;
 
291
        
 
292
        switch (pSetting->type)
 
293
        {
 
294
                case G_TYPE_INT:
 
295
                        g_key_file_set_integer (pKeyFile, cGroupName, cKeyName, pSetting->iValue);
 
296
                break;
 
297
                case G_TYPE_BOOLEAN:
 
298
                        g_key_file_set_boolean (pKeyFile, cGroupName, cKeyName, pSetting->iValue);
 
299
                break;
 
300
                case G_TYPE_STRING:
 
301
                        g_key_file_set_string (pKeyFile, cGroupName, cKeyName, pSetting->cValue);
 
302
                break;
 
303
                case G_TYPE_UINT64:
 
304
                {
 
305
                        int color[4];
 
306
                        int i;
 
307
                        for (i = 0; i < 4; i ++)
 
308
                                color[i] = pSetting->color[i];
 
309
                        g_key_file_set_integer_list (pKeyFile, cGroupName, cKeyName, color, 4);
 
310
                }
 
311
                break;
 
312
                default:
 
313
                return;
 
314
        }
 
315
        
 
316
        gsize length=0;
 
317
        gchar *cContent = g_key_file_to_data (pKeyFile, &length, &error);
 
318
        if (error != NULL)
 
319
        {
 
320
                g_warning ("can't write settings: %s", error->message);
 
321
                g_error_free (error);
 
322
                return ;
 
323
        }
 
324
        g_return_if_fail (cContent != NULL && *cContent != '\0');
 
325
        
 
326
        g_file_set_contents (cConfFilePath, cContent, length, &error);
 
327
        if (error != NULL)
 
328
        {
 
329
                g_warning ("can't write settings into %s: %s", cConfFilePath, error->message);
 
330
                g_error_free (error);
 
331
                return ;
 
332
        }
 
333
        g_free (cContent);
 
334
        
 
335
        g_free (cConfFilePath);
 
336
}
 
337
 
 
338
static void _load_stored_settings (void)
 
339
{
 
340
        gchar *cConfFilePath = g_strdup_printf ("%s/.config/xsettings.conf", g_getenv ("HOME"));
 
341
        if (! g_file_test (cConfFilePath, G_FILE_TEST_EXISTS))
 
342
        {
 
343
                /// copy from /usr/share...
 
344
                
 
345
        }
 
346
        GKeyFile *pKeyFile = g_key_file_new ();
 
347
        GError *error = NULL;
 
348
        g_key_file_load_from_file (pKeyFile, cConfFilePath, 0, &error);
 
349
        if (error != NULL)
 
350
        {
 
351
                g_warning ("couldn't parse %s : %s", cConfFilePath, error->message);
 
352
                return ;
 
353
        }
 
354
        g_free (cConfFilePath);
 
355
        
 
356
        // store the default settings.
 
357
        gsize length = 0;
 
358
        gchar **pGroupList = g_key_file_get_groups (pKeyFile, &length);
 
359
        g_return_if_fail (pGroupList != NULL);
 
360
        
 
361
        gchar **pKeyList;
 
362
        Setting *pSetting;
 
363
        const gchar *cGroupName, *cKeyName;
 
364
        gchar *cSettingName;
 
365
        int i, j;
 
366
        for (i = 0; pGroupList[i] != NULL; i ++)
 
367
        {
 
368
                cGroupName = pGroupList[i];
 
369
                
 
370
                // get the keys of the group.
 
371
                length = 0;
 
372
                pKeyList = g_key_file_get_keys (pKeyFile, cGroupName, NULL, NULL);
 
373
                g_return_if_fail (pKeyList != NULL);
 
374
                
 
375
                for (j = 0; pKeyList[j] != NULL; j ++)
 
376
                {
 
377
                        cKeyName = pKeyList[j];
 
378
                        
 
379
                        cSettingName = g_strdup_printf ("%s/%s", cGroupName, cKeyName);
 
380
                        g_print (" + %s\n", cSettingName);
 
381
                        
 
382
                        pSetting = g_hash_table_lookup (pSettings, cSettingName);
 
383
                        if (! pSetting)  // unknown setting, guess its type from its value.
 
384
                        {
 
385
                                Setting *pSetting = g_new0 (Setting, 1);
 
386
                                gchar *cValue = g_key_file_get_string (pKeyFile, cGroupName, cKeyName, &error);
 
387
                                if (error != NULL || cValue == NULL)  // it can be empty though.
 
388
                                {
 
389
                                        g_warning ("wrong property %s: %s", cSettingName, error ? error->message : "empty value");
 
390
                                        if (error) g_error_free (error);
 
391
                                        error = NULL;
 
392
                                        g_free (cSettingName);
 
393
                                        continue;
 
394
                                }
 
395
                                if (g_ascii_isdigit (*cValue) || *cValue == '-')
 
396
                                {
 
397
                                        if (strchr (cValue, ';') != NULL)  // a color is a list of 4 short
 
398
                                        {
 
399
                                                pSetting->type = G_TYPE_UINT64;
 
400
                                                gchar **rgba = g_strsplit (cValue, ";", -1);
 
401
                                                int i;
 
402
                                                for (i = 0; i < 4 && rgba[i] != NULL; i ++)
 
403
                                                {
 
404
                                                        pSetting->color[i] = atoi(rgba[i]);
 
405
                                                }
 
406
                                                g_strfreev (rgba);
 
407
                                        }
 
408
                                        else
 
409
                                        {
 
410
                                                pSetting->type = G_TYPE_INT;
 
411
                                                pSetting->iValue = atoi (cValue);
 
412
                                        }
 
413
                                }
 
414
                                else if (strcmp (cValue, "true") == 0 || strcmp (cValue, "false") == 0)
 
415
                                {
 
416
                                        pSetting->type = G_TYPE_BOOLEAN;
 
417
                                        pSetting->iValue = (*cValue == 't');
 
418
                                }
 
419
                                else
 
420
                                {
 
421
                                        pSetting->type = G_TYPE_STRING;
 
422
                                        pSetting->cValue = cValue;
 
423
                                        cValue = NULL;
 
424
                                        g_print (" + unknown setting of type 'string' (%s)\n",pSetting->cValue );
 
425
                                }
 
426
                                pSetting->iSerial = serial;
 
427
                                g_hash_table_insert (pSettings, cSettingName, pSetting);
 
428
                                cSettingName = NULL;
 
429
                                g_free (cValue);
 
430
                                continue;
 
431
                        }
 
432
                        
 
433
                        switch (pSetting->type)
 
434
                        {
 
435
                                case G_TYPE_BOOLEAN:
 
436
                                        pSetting->iValue = g_key_file_get_boolean (pKeyFile, cGroupName, cKeyName, &error);  // 0 or 1
 
437
                                break;
 
438
                                case G_TYPE_INT:
 
439
                                        pSetting->iValue = g_key_file_get_integer (pKeyFile, cGroupName, cKeyName, &error);
 
440
                                break;
 
441
                                case G_TYPE_STRING:
 
442
                                        pSetting->cValue = g_key_file_get_string (pKeyFile, cGroupName, cKeyName, &error);
 
443
                                break;
 
444
                                case G_TYPE_UINT64:
 
445
                                {
 
446
                                        int *rgba = g_key_file_get_integer_list (pKeyFile, cGroupName, cKeyName, &length, &error);
 
447
                                        int i;
 
448
                                        for (i = 0; i < 4 && i < length; i ++)
 
449
                                        {
 
450
                                                pSetting->color[i] = rgba[i];
 
451
                                        }
 
452
                                        g_free (rgba);
 
453
                                }
 
454
                                break;
 
455
                                default:
 
456
                                        g_warning ("bad property type for %s", cSettingName);
 
457
                                        g_free (cSettingName);
 
458
                                        continue;
 
459
                                break;
 
460
                        }
 
461
                        if (error != NULL)
 
462
                        {
 
463
                                g_warning ("wrong property %s: %s", cSettingName, error->message);
 
464
                                g_error_free (error);
 
465
                                error = NULL;
 
466
                                g_free (cSettingName);
 
467
                                continue;
 
468
                        }
 
469
                        
 
470
                        pSetting->iSerial = serial;
 
471
                        g_free (cSettingName);
 
472
                }
 
473
                g_strfreev (pKeyList);
 
474
        }
 
475
        g_strfreev (pGroupList);
 
476
        
 
477
        g_key_file_free (pKeyFile);
 
478
}
 
479
 
 
480
 
 
481
  //////////////////////
 
482
 /// DBUS INTERFACE ///
 
483
//////////////////////
 
484
 
 
485
G_DEFINE_TYPE(dbusMainObject, xsettings, G_TYPE_OBJECT);
 
486
 
 
487
gboolean xsettings_set (dbusMainObject *pDbusObject, const gchar *cSettingName, GValue *pValue, GError **error)
 
488
{
 
489
        // update the setting with the given value.
 
490
        g_print ("%s (%s)\n", __func__, cSettingName);
 
491
        Setting *pSetting = g_hash_table_lookup (pSettings, cSettingName);
 
492
        g_return_val_if_fail (pSetting != NULL, FALSE);  // let's ignore unexisting settings.
 
493
        
 
494
        switch (pSetting->type)
 
495
        {
 
496
                case G_TYPE_BOOLEAN:
 
497
                        if (! G_VALUE_HOLDS_BOOLEAN (pValue))
 
498
                                return FALSE;
 
499
                        pSetting->iValue = g_value_get_boolean (pValue);
 
500
                break;
 
501
                case G_TYPE_INT:
 
502
                        if (! G_VALUE_HOLDS_INT (pValue))
 
503
                                return FALSE;
 
504
                        pSetting->iValue = g_value_get_int (pValue);
 
505
                break;
 
506
                case G_TYPE_STRING:
 
507
                        if (! G_VALUE_HOLDS_STRING (pValue))
 
508
                                return FALSE;
 
509
                        g_free (pSetting->cValue);
 
510
                        pSetting->cValue = g_strdup (g_value_get_string (pValue));
 
511
                break;
 
512
                case G_TYPE_UINT64:
 
513
                {
 
514
                        if (! G_VALUE_HOLDS_BOXED (pValue))
 
515
                                return FALSE;
 
516
                        GArray *a = g_value_get_boxed (pValue);  /// TODO: check that Python actually makes a GArray.
 
517
                        int i;
 
518
                        for (i = 0; i < 4 && i < a->len; i ++)
 
519
                        {
 
520
                                g_print ("color %d: %d\n", i, g_array_index (a, int, i));
 
521
                                pSetting->color[i] = g_array_index (a, int, i);
 
522
                        }
 
523
                        /*gchar **rgba = g_strsplit (cValue, ";", -1);
 
524
                        int i;
 
525
                        for (i = 0; i < 4 && rgba[i] != NULL; i ++)
 
526
                        {
 
527
                                pSetting->color[i] = atoi(rgba[i]);
 
528
                        }
 
529
                        g_strfreev (rgba);*/
 
530
                }
 
531
                break;
 
532
                default:
 
533
                return FALSE;
 
534
        }
 
535
        pSetting->iSerial = serial;
 
536
        
 
537
        // store the new setting value in the conf file.
 
538
        _store_setting (cSettingName, pSetting);
 
539
        
 
540
        // update the X settings.
 
541
        _update_settings_on_X ();
 
542
        
 
543
        return TRUE;
 
544
}
 
545
 
 
546
 
 
547
static void xsettings_class_init(dbusMainObjectClass *klass)
 
548
{
 
549
        
 
550
}
 
551
static void xsettings_init (dbusMainObject *pDbusObject)
 
552
{
 
553
        dbus_g_object_type_install_info(xsettings_get_type(), &dbus_glib_xsettings_object_info);
 
554
        
 
555
        GError *error = NULL;
 
556
        DBusGConnection *connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
 
557
        if (error != NULL)
 
558
        {
 
559
                g_warning ("%s\n", error->message);
 
560
                g_error_free (error);
 
561
        }
 
562
        else
 
563
        {
 
564
                dbus_g_connection_register_g_object (connection, "/Manager", G_OBJECT(pDbusObject));
 
565
        }
 
566
}
 
567
 
 
568
static void _register_dbus_interface (void)
 
569
{
 
570
        g_type_init();
 
571
        GError *error = NULL;
 
572
        DBusGConnection *pConnection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
 
573
        if (error != NULL)
 
574
        {
 
575
                g_warning ("Dbus error: %s", error->message);
 
576
                g_error_free (error);
 
577
                error = NULL;
 
578
        }
 
579
        else
 
580
        {
 
581
                DBusGProxy *pSessionProxy = dbus_g_proxy_new_for_name (
 
582
                        pConnection,
 
583
                        DBUS_SERVICE_DBUS,
 
584
                        DBUS_PATH_DBUS,
 
585
                        DBUS_INTERFACE_DBUS);
 
586
                
 
587
                int request_ret;
 
588
                org_freedesktop_DBus_request_name (pSessionProxy, "org.cairodock.xsettings", 0, &request_ret, &error);
 
589
                if (error != NULL)
 
590
                {
 
591
                        g_warning ("Dbus error: %s", error->message);
 
592
                        g_error_free (error);
 
593
                        error = NULL;
 
594
                }
 
595
                else
 
596
                {
 
597
                        pMainObject = g_object_new (xsettings_get_type(), NULL);
 
598
                }
 
599
        }
 
600
}
 
601
 
 
602
 
 
603
  ////////////
 
604
 /// MAIN ///
 
605
////////////
 
606
 
 
607
 
 
608
typedef struct 
 
609
{
 
610
  Window window;
 
611
  Atom timestamp_prop_atom;
 
612
} TimeStampInfo;
 
613
 
 
614
static Bool
 
615
timestamp_predicate (Display *display,
 
616
                     XEvent  *xevent,
 
617
                     XPointer arg)
 
618
{
 
619
  TimeStampInfo *info = (TimeStampInfo *)arg;
 
620
 
 
621
  if (xevent->type == PropertyNotify &&
 
622
      xevent->xproperty.window == info->window &&
 
623
      xevent->xproperty.atom == info->timestamp_prop_atom)
 
624
    return True;
 
625
 
 
626
  return False;
 
627
}
 
628
 
 
629
int main (int argc, char** argv)
 
630
{
 
631
        // init the X session.
 
632
        gdk_init(&argc, &argv);
 
633
        XSetErrorHandler (_xerror_handler);
 
634
        GdkDisplay *gdpy = gdk_display_get_default();
 
635
        dpy = GDK_DISPLAY_XDISPLAY(gdpy);
 
636
        //dpy = XOpenDisplay (NULL);
 
637
        g_return_val_if_fail (dpy != NULL, 1);
 
638
        
 
639
        int screen = DefaultScreen (dpy);
 
640
        
 
641
        Window root = RootWindow (dpy, screen);
 
642
        
 
643
        XSetErrorHandler (_xerror_handler);
 
644
        
 
645
        gchar *xsetting_sn = g_strdup_printf ("_XSETTINGS_S%d", DefaultScreen(dpy));
 
646
        selection_atom = XInternAtom (dpy, xsetting_sn, False);
 
647
        g_free (xsetting_sn);
 
648
        xsettings_atom = XInternAtom (dpy, "_XSETTINGS_SETTINGS", False) ;
 
649
        
 
650
        // create an client (an invisible small X window).
 
651
        window = XCreateSimpleWindow (dpy,
 
652
                root,
 
653
                0, 0, 10, 10, 0,
 
654
                WhitePixel (dpy, screen),
 
655
                WhitePixel (dpy, screen));
 
656
        g_return_val_if_fail (window != 0, 1);
 
657
        
 
658
        // acquire the XSETTINGS selection.
 
659
        int time = CurrentTime;
 
660
        XSetSelectionOwner (dpy, selection_atom, window, time);
 
661
        
 
662
        //  check that we could acquire it.
 
663
        if (XGetSelectionOwner (dpy, selection_atom) != window)
 
664
        {
 
665
                g_warning ("Couldn't acquire the selection, another XSettings Manager is probably running.");
 
666
                return 2;
 
667
        }
 
668
        
 
669
        // notify all the other clients that we are here.
 
670
        XClientMessageEvent xev;
 
671
        
 
672
        xev.type = ClientMessage;
 
673
        xev.window = root;
 
674
        xev.message_type = XInternAtom (dpy, "MANAGER", False);
 
675
        xev.format = 32;
 
676
        xev.data.l[0] = time;
 
677
        xev.data.l[1] = selection_atom;
 
678
        xev.data.l[2] = window;
 
679
        xev.data.l[3] = 0;
 
680
        xev.data.l[4] = 0;
 
681
        
 
682
        XSendEvent (dpy, root, False, StructureNotifyMask, (XEvent *)&xev);
 
683
        
 
684
        // register the known settings
 
685
        register_settings ();
 
686
        
 
687
        // init the settings with their default values.
 
688
        _load_stored_settings ();
 
689
        
 
690
        // update the XSettings property with the settings.
 
691
        _update_settings_on_X ();
 
692
        
 
693
        // Dbus
 
694
        _register_dbus_interface ();
 
695
        
 
696
        // enter the main loop.
 
697
        GMainLoop *loop = g_main_loop_new (NULL, FALSE);
 
698
        g_main_loop_run (loop);
 
699
        
 
700
        return 0;
 
701
}