~seb128/unity-settings-daemon/battery-info-key

« back to all changes in this revision

Viewing changes to plugins/xsettings/gnome-xsettings-manager.c

  • Committer: William Jon McCann
  • Author(s): William Jon McCann
  • Date: 2007-12-14 05:06:55 UTC
  • Revision ID: git-v1:b7f5d9895c19338f10b0bdd494b221b13b540d9d
Initial checkin. Previously lived in gdm module.

2007-12-14  William Jon McCann  <mccann@jhu.edu>

        * configure.ac, etc: Initial checkin.  Previously
        lived in gdm module.


svn path=/trunk/; revision=2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2007 Rodrigo Moya
 
4
 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
19
 *
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <sys/types.h>
 
25
#include <sys/wait.h>
 
26
#include <stdlib.h>
 
27
#include <stdio.h>
 
28
#include <unistd.h>
 
29
#include <string.h>
 
30
#include <errno.h>
 
31
 
 
32
#include <locale.h>
 
33
 
 
34
#include <glib.h>
 
35
#include <glib/gi18n.h>
 
36
#include <gdk/gdk.h>
 
37
#include <gdk/gdkx.h>
 
38
#include <gtk/gtk.h>
 
39
#include <gconf/gconf.h>
 
40
#include <gconf/gconf-client.h>
 
41
 
 
42
#include "gnome-xsettings-manager.h"
 
43
#include "xsettings-manager.h"
 
44
 
 
45
#define GNOME_XSETTINGS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GNOME_TYPE_XSETTINGS_MANAGER, GnomeXSettingsManagerPrivate))
 
46
 
 
47
#ifdef HAVE_XFT2
 
48
#define FONT_RENDER_DIR "/desktop/gnome/font_rendering"
 
49
#define FONT_ANTIALIASING_KEY FONT_RENDER_DIR "/antialiasing"
 
50
#define FONT_HINTING_KEY      FONT_RENDER_DIR "/hinting"
 
51
#define FONT_RGBA_ORDER_KEY   FONT_RENDER_DIR "/rgba_order"
 
52
#define FONT_DPI_KEY          FONT_RENDER_DIR "/dpi"
 
53
 
 
54
/* X servers sometimes lie about the screen's physical dimensions, so we cannot
 
55
 * compute an accurate DPI value.  When this happens, the user gets fonts that
 
56
 * are too huge or too tiny.  So, we see what the server returns:  if it reports
 
57
 * something outside of the range [DPI_LOW_REASONABLE_VALUE,
 
58
 * DPI_HIGH_REASONABLE_VALUE], then we assume that it is lying and we use
 
59
 * DPI_FALLBACK instead.
 
60
 *
 
61
 * See get_dpi_from_gconf_or_server() below, and also
 
62
 * https://bugzilla.novell.com/show_bug.cgi?id=217790
 
63
 */
 
64
#define DPI_FALLBACK 96
 
65
#define DPI_LOW_REASONABLE_VALUE 50
 
66
#define DPI_HIGH_REASONABLE_VALUE 500
 
67
 
 
68
#endif /* HAVE_XFT2 */
 
69
 
 
70
typedef struct _TranslationEntry TranslationEntry;
 
71
typedef void (* TranslationFunc) (GnomeXSettingsManager *manager,
 
72
                                  TranslationEntry      *trans,
 
73
                                  GConfValue            *value);
 
74
 
 
75
struct _TranslationEntry {
 
76
        const char     *gconf_key;
 
77
        const char     *xsetting_name;
 
78
 
 
79
        GConfValueType  gconf_type;
 
80
        TranslationFunc translate;
 
81
};
 
82
 
 
83
struct GnomeXSettingsManagerPrivate
 
84
{
 
85
        XSettingsManager **managers;
 
86
};
 
87
 
 
88
enum {
 
89
        PROP_0,
 
90
};
 
91
 
 
92
static void     gnome_xsettings_manager_class_init  (GnomeXSettingsManagerClass *klass);
 
93
static void     gnome_xsettings_manager_init        (GnomeXSettingsManager      *xsettings_manager);
 
94
static void     gnome_xsettings_manager_finalize    (GObject                  *object);
 
95
 
 
96
G_DEFINE_TYPE (GnomeXSettingsManager, gnome_xsettings_manager, G_TYPE_OBJECT)
 
97
 
 
98
static gpointer manager_object = NULL;
 
99
 
 
100
static void
 
101
translate_bool_int (GnomeXSettingsManager *manager,
 
102
                    TranslationEntry      *trans,
 
103
                    GConfValue            *value)
 
104
{
 
105
        int i;
 
106
 
 
107
        g_assert (value->type == trans->gconf_type);
 
108
 
 
109
        for (i = 0; manager->priv->managers [i]; i++) {
 
110
                xsettings_manager_set_int (manager->priv->managers [i], trans->xsetting_name,
 
111
                                           gconf_value_get_bool (value));
 
112
        }
 
113
}
 
114
 
 
115
static void
 
116
translate_int_int (GnomeXSettingsManager *manager,
 
117
                   TranslationEntry      *trans,
 
118
                   GConfValue            *value)
 
119
{
 
120
        int i;
 
121
 
 
122
        g_assert (value->type == trans->gconf_type);
 
123
 
 
124
        for (i = 0; manager->priv->managers [i]; i++) {
 
125
                xsettings_manager_set_int (manager->priv->managers [i], trans->xsetting_name,
 
126
                                           gconf_value_get_int (value));
 
127
        }
 
128
}
 
129
 
 
130
static void
 
131
translate_string_string (GnomeXSettingsManager *manager,
 
132
                         TranslationEntry      *trans,
 
133
                         GConfValue            *value)
 
134
{
 
135
        int i;
 
136
 
 
137
        g_assert (value->type == trans->gconf_type);
 
138
 
 
139
        for (i = 0; manager->priv->managers [i]; i++) {
 
140
                xsettings_manager_set_string (manager->priv->managers [i],
 
141
                                              trans->xsetting_name,
 
142
                                              gconf_value_get_string (value));
 
143
        }
 
144
}
 
145
 
 
146
static void
 
147
translate_string_string_toolbar (GnomeXSettingsManager *manager,
 
148
                                 TranslationEntry      *trans,
 
149
                                 GConfValue            *value)
 
150
{
 
151
        int         i;
 
152
        const char *tmp;
 
153
 
 
154
        g_assert (value->type == trans->gconf_type);
 
155
 
 
156
        /* This is kind of a workaround since GNOME expects the key value to be
 
157
         * "both_horiz" and gtk+ wants the XSetting to be "both-horiz".
 
158
         */
 
159
        tmp = gconf_value_get_string (value);
 
160
        if (tmp && strcmp (tmp, "both_horiz") == 0) {
 
161
                tmp = "both-horiz";
 
162
        }
 
163
 
 
164
        for (i = 0; manager->priv->managers [i]; i++) {
 
165
                xsettings_manager_set_string (manager->priv->managers [i],
 
166
                                              trans->xsetting_name,
 
167
                                              tmp);
 
168
        }
 
169
}
 
170
 
 
171
static TranslationEntry translations [] = {
 
172
        { "/desktop/gnome/peripherals/mouse/double_click",   "Net/DoubleClickTime",     GCONF_VALUE_INT,      translate_int_int },
 
173
        { "/desktop/gnome/peripherals/mouse/drag_threshold", "Net/DndDragThreshold",    GCONF_VALUE_INT,      translate_int_int },
 
174
        { "/desktop/gnome/gtk-color-palette",                "Gtk/ColorPalette",        GCONF_VALUE_STRING,   translate_string_string },
 
175
        { "/desktop/gnome/interface/font_name",              "Gtk/FontName",            GCONF_VALUE_STRING,   translate_string_string },
 
176
        { "/desktop/gnome/interface/gtk_key_theme",          "Gtk/KeyThemeName",        GCONF_VALUE_STRING,   translate_string_string },
 
177
        { "/desktop/gnome/interface/toolbar_style",          "Gtk/ToolbarStyle",        GCONF_VALUE_STRING,   translate_string_string_toolbar },
 
178
        { "/desktop/gnome/interface/toolbar_icon_size",      "Gtk/ToolbarIconSize",     GCONF_VALUE_STRING,   translate_string_string },
 
179
        { "/desktop/gnome/interface/can_change_accels",      "Gtk/CanChangeAccels",     GCONF_VALUE_BOOL,     translate_bool_int },
 
180
        { "/desktop/gnome/interface/cursor_blink",           "Net/CursorBlink",         GCONF_VALUE_BOOL,     translate_bool_int },
 
181
        { "/desktop/gnome/interface/cursor_blink_time",      "Net/CursorBlinkTime",     GCONF_VALUE_INT,      translate_int_int },
 
182
        { "/desktop/gnome/interface/gtk_theme",              "Net/ThemeName",           GCONF_VALUE_STRING,   translate_string_string },
 
183
        { "/desktop/gnome/interface/gtk_color_scheme",       "Gtk/ColorScheme",         GCONF_VALUE_STRING,   translate_string_string },
 
184
        { "/desktop/gnome/interface/gtk-im-preedit-style",   "Gtk/IMPreeditStyle",      GCONF_VALUE_STRING,   translate_string_string },
 
185
        { "/desktop/gnome/interface/gtk-im-status-style",    "Gtk/IMStatusStyle",       GCONF_VALUE_STRING,   translate_string_string },
 
186
        { "/desktop/gnome/interface/icon_theme",             "Net/IconThemeName",       GCONF_VALUE_STRING,   translate_string_string },
 
187
        { "/desktop/gnome/interface/file_chooser_backend",   "Gtk/FileChooserBackend",  GCONF_VALUE_STRING,   translate_string_string },
 
188
        { "/desktop/gnome/interface/menus_have_icons",       "Gtk/MenuImages",          GCONF_VALUE_BOOL,     translate_bool_int },
 
189
        { "/desktop/gnome/interface/menubar_accel",          "Gtk/MenuBarAccel",        GCONF_VALUE_STRING,   translate_string_string },
 
190
        { "/desktop/gnome/peripherals/mouse/cursor_theme",   "Gtk/CursorThemeName",     GCONF_VALUE_STRING,   translate_string_string },
 
191
        { "/desktop/gnome/peripherals/mouse/cursor_size",    "Gtk/CursorThemeSize",     GCONF_VALUE_INT,      translate_int_int },
 
192
        { "/desktop/gnome/interface/show_input_method_menu", "Gtk/ShowInputMethodMenu", GCONF_VALUE_BOOL,     translate_bool_int },
 
193
        { "/desktop/gnome/interface/show_unicode_menu",      "Gtk/ShowUnicodeMenu",     GCONF_VALUE_BOOL,     translate_bool_int },
 
194
};
 
195
 
 
196
#ifdef HAVE_XFT2
 
197
static double
 
198
dpi_from_pixels_and_mm (int pixels,
 
199
                        int mm)
 
200
{
 
201
        double dpi;
 
202
 
 
203
        if (mm >= 1)
 
204
                dpi = pixels / (mm / 25.4);
 
205
        else
 
206
                dpi = 0;
 
207
 
 
208
        return dpi;
 
209
}
 
210
 
 
211
static double
 
212
get_dpi_from_x_server (void)
 
213
{
 
214
        GdkScreen *screen;
 
215
        double     dpi;
 
216
 
 
217
        screen = gdk_screen_get_default ();
 
218
        if (screen != NULL) {
 
219
                double width_dpi, height_dpi;
 
220
 
 
221
                width_dpi = dpi_from_pixels_and_mm (gdk_screen_get_width (screen), gdk_screen_get_width_mm (screen));
 
222
                height_dpi = dpi_from_pixels_and_mm (gdk_screen_get_height (screen), gdk_screen_get_height_mm (screen));
 
223
 
 
224
                if (width_dpi < DPI_LOW_REASONABLE_VALUE || width_dpi > DPI_HIGH_REASONABLE_VALUE
 
225
                    || height_dpi < DPI_LOW_REASONABLE_VALUE || height_dpi > DPI_HIGH_REASONABLE_VALUE) {
 
226
                        dpi = DPI_FALLBACK;
 
227
                } else {
 
228
                        dpi = (width_dpi + height_dpi) / 2.0;
 
229
                }
 
230
        } else {
 
231
                /* Huh!?  No screen? */
 
232
 
 
233
                dpi = DPI_FALLBACK;
 
234
        }
 
235
 
 
236
        return dpi;
 
237
}
 
238
 
 
239
static double
 
240
get_dpi_from_gconf_or_x_server (GConfClient *client)
 
241
{
 
242
        GConfValue *value;
 
243
        double      dpi;
 
244
 
 
245
        value = gconf_client_get_without_default (client, FONT_DPI_KEY, NULL);
 
246
 
 
247
        /* If the user has ever set the DPI preference in GConf, we use that.
 
248
         * Otherwise, we see if the X server reports a reasonable DPI value:  some X
 
249
         * servers report completely bogus values, and the user gets huge or tiny
 
250
         * fonts which are unusable.
 
251
         */
 
252
 
 
253
        if (value != NULL) {
 
254
                dpi = gconf_value_get_float (value);
 
255
                gconf_value_free (value);
 
256
        } else {
 
257
                dpi = get_dpi_from_x_server ();
 
258
        }
 
259
 
 
260
        return dpi;
 
261
}
 
262
 
 
263
typedef struct
 
264
{
 
265
        gboolean    antialias;
 
266
        gboolean    hinting;
 
267
        int         dpi;
 
268
        const char *rgba;
 
269
        const char *hintstyle;
 
270
} GnomeXftSettings;
 
271
 
 
272
static const char *rgba_types[] = { "rgb", "bgr", "vbgr", "vrgb" };
 
273
 
 
274
/* Read GConf settings and determine the appropriate Xft settings based on them
 
275
 * This probably could be done a bit more cleanly with gconf_string_to_enum
 
276
 */
 
277
static void
 
278
xft_settings_get (GConfClient      *client,
 
279
                  GnomeXftSettings *settings)
 
280
{
 
281
        char  *antialiasing;
 
282
        char  *hinting;
 
283
        char  *rgba_order;
 
284
        double dpi;
 
285
 
 
286
        antialiasing = gconf_client_get_string (client, FONT_ANTIALIASING_KEY, NULL);
 
287
        hinting = gconf_client_get_string (client, FONT_HINTING_KEY, NULL);
 
288
        rgba_order = gconf_client_get_string (client, FONT_RGBA_ORDER_KEY, NULL);
 
289
        dpi = get_dpi_from_gconf_or_x_server (client);
 
290
 
 
291
        settings->antialias = TRUE;
 
292
        settings->hinting = TRUE;
 
293
        settings->hintstyle = "hintfull";
 
294
        settings->dpi = dpi * 1024; /* Xft wants 1/1024ths of an inch */
 
295
        settings->rgba = "rgb";
 
296
 
 
297
        if (rgba_order) {
 
298
                int i;
 
299
                gboolean found = FALSE;
 
300
 
 
301
                for (i = 0; i < G_N_ELEMENTS (rgba_types) && !found; i++) {
 
302
                        if (strcmp (rgba_order, rgba_types[i]) == 0) {
 
303
                                settings->rgba = rgba_types[i];
 
304
                                found = TRUE;
 
305
                        }
 
306
                }
 
307
 
 
308
                if (!found) {
 
309
                        g_warning ("Invalid value for " FONT_RGBA_ORDER_KEY ": '%s'",
 
310
                                   rgba_order);
 
311
                }
 
312
        }
 
313
 
 
314
        if (hinting) {
 
315
                if (strcmp (hinting, "none") == 0) {
 
316
                        settings->hinting = 0;
 
317
                        settings->hintstyle = "hintnone";
 
318
                } else if (strcmp (hinting, "slight") == 0) {
 
319
                        settings->hinting = 1;
 
320
                        settings->hintstyle = "hintslight";
 
321
                } else if (strcmp (hinting, "medium") == 0) {
 
322
                        settings->hinting = 1;
 
323
                        settings->hintstyle = "hintmedium";
 
324
                } else if (strcmp (hinting, "full") == 0) {
 
325
                        settings->hinting = 1;
 
326
                        settings->hintstyle = "hintfull";
 
327
                } else {
 
328
                        g_warning ("Invalid value for " FONT_HINTING_KEY ": '%s'",
 
329
                                   hinting);
 
330
                }
 
331
        }
 
332
 
 
333
        if (antialiasing) {
 
334
                gboolean use_rgba = FALSE;
 
335
 
 
336
                if (strcmp (antialiasing, "none") == 0) {
 
337
                        settings->antialias = 0;
 
338
                } else if (strcmp (antialiasing, "grayscale") == 0) {
 
339
                        settings->antialias = 1;
 
340
                } else if (strcmp (antialiasing, "rgba") == 0) {
 
341
                        settings->antialias = 1;
 
342
                        use_rgba = TRUE;
 
343
                } else {
 
344
                        g_warning ("Invalid value for " FONT_ANTIALIASING_KEY " : '%s'",
 
345
                                   antialiasing);
 
346
                }
 
347
 
 
348
                if (!use_rgba) {
 
349
                        settings->rgba = "none";
 
350
                }
 
351
        }
 
352
 
 
353
        g_free (rgba_order);
 
354
        g_free (hinting);
 
355
        g_free (antialiasing);
 
356
}
 
357
 
 
358
static void
 
359
xft_settings_set_xsettings (GnomeXSettingsManager *manager,
 
360
                            GnomeXftSettings      *settings)
 
361
{
 
362
        int i;
 
363
        for (i = 0; manager->priv->managers [i]; i++) {
 
364
                xsettings_manager_set_int (manager->priv->managers [i], "Xft/Antialias", settings->antialias);
 
365
                xsettings_manager_set_int (manager->priv->managers [i], "Xft/Hinting", settings->hinting);
 
366
                xsettings_manager_set_string (manager->priv->managers [i], "Xft/HintStyle", settings->hintstyle);
 
367
                xsettings_manager_set_int (manager->priv->managers [i], "Xft/DPI", settings->dpi);
 
368
                xsettings_manager_set_string (manager->priv->managers [i], "Xft/RGBA", settings->rgba);
 
369
        }
 
370
}
 
371
 
 
372
static gboolean
 
373
write_all (int         fd,
 
374
           const char *buf,
 
375
           gsize       to_write)
 
376
{
 
377
        while (to_write > 0) {
 
378
                gssize count = write (fd, buf, to_write);
 
379
                if (count < 0) {
 
380
                        if (errno != EINTR)
 
381
                                return FALSE;
 
382
                } else {
 
383
                        to_write -= count;
 
384
                        buf += count;
 
385
                }
 
386
        }
 
387
 
 
388
        return TRUE;
 
389
}
 
390
 
 
391
static void
 
392
child_watch_cb (GPid     pid,
 
393
                int      status,
 
394
                gpointer user_data)
 
395
{
 
396
        char *command = user_data;
 
397
 
 
398
        if (!WIFEXITED (status) || WEXITSTATUS (status)) {
 
399
                g_warning ("Command %s failed", command);
 
400
        }
 
401
}
 
402
 
 
403
static void
 
404
spawn_with_input (const char *command,
 
405
                  const char *input)
 
406
{
 
407
        char   **argv;
 
408
        int      child_pid;
 
409
        int      inpipe;
 
410
        GError  *error;
 
411
        gboolean res;
 
412
 
 
413
        argv = NULL;
 
414
        res = g_shell_parse_argv (command, NULL, &argv, NULL);
 
415
        if (! res) {
 
416
                g_warning ("Unable to parse command: %s", command);
 
417
                return;
 
418
        }
 
419
 
 
420
        error = NULL;
 
421
        res = g_spawn_async_with_pipes (NULL,
 
422
                                        argv,
 
423
                                        NULL,
 
424
                                        G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
 
425
                                        NULL,
 
426
                                        NULL,
 
427
                                        &child_pid,
 
428
                                        &inpipe,
 
429
                                        NULL,
 
430
                                        NULL,
 
431
                                        &error);
 
432
        g_strfreev (argv);
 
433
 
 
434
        if (! res) {
 
435
                g_warning ("Could not execute %s: %s", command, error->message);
 
436
                g_error_free (error);
 
437
 
 
438
                return;
 
439
        }
 
440
 
 
441
        if (input != NULL) {
 
442
                if (! write_all (inpipe, input, strlen (input))) {
 
443
                        g_warning ("Could not write input to %s", command);
 
444
                }
 
445
 
 
446
                close (inpipe);
 
447
        }
 
448
 
 
449
        g_child_watch_add (child_pid, (GChildWatchFunc) child_watch_cb, (gpointer)command);
 
450
}
 
451
 
 
452
static void
 
453
xft_settings_set_xresources (GnomeXftSettings *settings)
 
454
{
 
455
        const char *command;
 
456
        GString    *add_string;
 
457
        char       *old_locale;
 
458
 
 
459
        command = "xrdb -nocpp -merge";
 
460
 
 
461
        add_string = g_string_new (NULL);
 
462
        old_locale = g_strdup (setlocale (LC_NUMERIC, NULL));
 
463
 
 
464
        setlocale (LC_NUMERIC, "C");
 
465
        g_string_append_printf (add_string,
 
466
                                "Xft.dpi: %f\n",
 
467
                                settings->dpi / 1024.0);
 
468
        g_string_append_printf (add_string,
 
469
                                "Xft.antialias: %d\n",
 
470
                                settings->antialias);
 
471
        g_string_append_printf (add_string,
 
472
                                "Xft.hinting: %d\n",
 
473
                                settings->hinting);
 
474
        g_string_append_printf (add_string,
 
475
                                "Xft.hintstyle: %s\n",
 
476
                                settings->hintstyle);
 
477
        g_string_append_printf (add_string,
 
478
                                "Xft.rgba: %s\n",
 
479
                                settings->rgba);
 
480
 
 
481
        spawn_with_input (command, add_string->str);
 
482
 
 
483
        g_string_free (add_string, TRUE);
 
484
        setlocale (LC_NUMERIC, old_locale);
 
485
        g_free (old_locale);
 
486
}
 
487
 
 
488
/* We mirror the Xft properties both through XSETTINGS and through
 
489
 * X resources
 
490
 */
 
491
static void
 
492
update_xft_settings (GnomeXSettingsManager *manager,
 
493
                     GConfClient           *client)
 
494
{
 
495
        GnomeXftSettings settings;
 
496
 
 
497
        xft_settings_get (client, &settings);
 
498
        xft_settings_set_xsettings (manager, &settings);
 
499
        xft_settings_set_xresources (&settings);
 
500
}
 
501
 
 
502
static void
 
503
xft_callback (GConfClient           *client,
 
504
              guint                  cnxn_id,
 
505
              GConfEntry            *entry,
 
506
              GnomeXSettingsManager *manager)
 
507
{
 
508
        int i;
 
509
 
 
510
        update_xft_settings (manager, client);
 
511
 
 
512
        for (i = 0; manager->priv->managers [i]; i++) {
 
513
                xsettings_manager_notify (manager->priv->managers [i]);
 
514
        }
 
515
}
 
516
 
 
517
#endif /* HAVE_XFT2 */
 
518
 
 
519
static const char *
 
520
type_to_string (GConfValueType type)
 
521
{
 
522
        switch (type) {
 
523
        case GCONF_VALUE_INT:
 
524
                return "int";
 
525
        case GCONF_VALUE_STRING:
 
526
                return "string";
 
527
        case GCONF_VALUE_FLOAT:
 
528
                return "float";
 
529
        case GCONF_VALUE_BOOL:
 
530
                return "bool";
 
531
        case GCONF_VALUE_SCHEMA:
 
532
                return "schema";
 
533
        case GCONF_VALUE_LIST:
 
534
                return "list";
 
535
        case GCONF_VALUE_PAIR:
 
536
                return "pair";
 
537
        case GCONF_VALUE_INVALID:
 
538
                return "*invalid*";
 
539
        default:
 
540
                g_assert_not_reached();
 
541
                return NULL; /* for warnings */
 
542
        }
 
543
}
 
544
 
 
545
static void
 
546
process_value (GnomeXSettingsManager *manager,
 
547
               TranslationEntry      *trans,
 
548
               GConfValue            *val)
 
549
{
 
550
        if (val == NULL) {
 
551
                int i;
 
552
 
 
553
                for (i = 0; manager->priv->managers [i]; i++) {
 
554
                        xsettings_manager_delete_setting (manager->priv->managers [i], trans->xsetting_name);
 
555
                }
 
556
        } else {
 
557
                if (val->type == trans->gconf_type) {
 
558
                        (* trans->translate) (manager, trans, val);
 
559
                } else {
 
560
                        g_warning (_("GConf key %s set to type %s but its expected type was %s\n"),
 
561
                                   trans->gconf_key,
 
562
                                   type_to_string (val->type),
 
563
                                   type_to_string (trans->gconf_type));
 
564
                }
 
565
        }
 
566
}
 
567
 
 
568
gboolean
 
569
gnome_xsettings_manager_start (GnomeXSettingsManager *manager,
 
570
                               GError               **error)
 
571
{
 
572
        GConfClient *client;
 
573
        int          i;
 
574
 
 
575
        g_debug ("Starting xsettings manager");
 
576
 
 
577
        client = gconf_client_get_default ();
 
578
 
 
579
        for (i = 0; i < G_N_ELEMENTS (translations); i++) {
 
580
                GConfValue *val;
 
581
                GError     *err;
 
582
 
 
583
                err = NULL;
 
584
                val = gconf_client_get (client,
 
585
                                        translations[i].gconf_key,
 
586
                                        &err);
 
587
 
 
588
                if (err != NULL) {
 
589
                        g_warning ("Error getting value for %s: %s\n",
 
590
                                   translations[i].gconf_key,
 
591
                                   err->message);
 
592
                        g_error_free (err);
 
593
                } else {
 
594
                        process_value (manager, &translations[i], val);
 
595
                        if (val != NULL) {
 
596
                                gconf_value_free (val);
 
597
                        }
 
598
                }
 
599
        }
 
600
 
 
601
        g_object_unref (client);
 
602
 
 
603
#ifdef HAVE_XFT2
 
604
        update_xft_settings (manager, client);
 
605
#endif /* HAVE_XFT */
 
606
 
 
607
        for (i = 0; manager->priv->managers [i]; i++)
 
608
                xsettings_manager_set_string (manager->priv->managers [i],
 
609
                                              "Net/FallbackIconTheme",
 
610
                                              "gnome");
 
611
 
 
612
        for (i = 0; manager->priv->managers [i]; i++) {
 
613
                xsettings_manager_notify (manager->priv->managers [i]);
 
614
        }
 
615
 
 
616
        return TRUE;
 
617
}
 
618
 
 
619
void
 
620
gnome_xsettings_manager_stop (GnomeXSettingsManager *manager)
 
621
{
 
622
        g_debug ("Stopping xsettings manager");
 
623
}
 
624
 
 
625
static void
 
626
gnome_xsettings_manager_set_property (GObject        *object,
 
627
                                      guint           prop_id,
 
628
                                      const GValue   *value,
 
629
                                      GParamSpec     *pspec)
 
630
{
 
631
        GnomeXSettingsManager *self;
 
632
 
 
633
        self = GNOME_XSETTINGS_MANAGER (object);
 
634
 
 
635
        switch (prop_id) {
 
636
        default:
 
637
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
638
                break;
 
639
        }
 
640
}
 
641
 
 
642
static void
 
643
gnome_xsettings_manager_get_property (GObject        *object,
 
644
                                      guint           prop_id,
 
645
                                      GValue         *value,
 
646
                                      GParamSpec     *pspec)
 
647
{
 
648
        GnomeXSettingsManager *self;
 
649
 
 
650
        self = GNOME_XSETTINGS_MANAGER (object);
 
651
 
 
652
        switch (prop_id) {
 
653
        default:
 
654
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
655
                break;
 
656
        }
 
657
}
 
658
 
 
659
static GObject *
 
660
gnome_xsettings_manager_constructor (GType                  type,
 
661
                                     guint                  n_construct_properties,
 
662
                                     GObjectConstructParam *construct_properties)
 
663
{
 
664
        GnomeXSettingsManager      *xsettings_manager;
 
665
        GnomeXSettingsManagerClass *klass;
 
666
 
 
667
        klass = GNOME_XSETTINGS_MANAGER_CLASS (g_type_class_peek (GNOME_TYPE_XSETTINGS_MANAGER));
 
668
 
 
669
        xsettings_manager = GNOME_XSETTINGS_MANAGER (G_OBJECT_CLASS (gnome_xsettings_manager_parent_class)->constructor (type,
 
670
                                                                                                                  n_construct_properties,
 
671
                                                                                                                  construct_properties));
 
672
 
 
673
        return G_OBJECT (xsettings_manager);
 
674
}
 
675
 
 
676
static void
 
677
gnome_xsettings_manager_dispose (GObject *object)
 
678
{
 
679
        GnomeXSettingsManager *xsettings_manager;
 
680
 
 
681
        xsettings_manager = GNOME_XSETTINGS_MANAGER (object);
 
682
 
 
683
        G_OBJECT_CLASS (gnome_xsettings_manager_parent_class)->dispose (object);
 
684
}
 
685
 
 
686
static void
 
687
gnome_xsettings_manager_class_init (GnomeXSettingsManagerClass *klass)
 
688
{
 
689
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
690
 
 
691
        object_class->get_property = gnome_xsettings_manager_get_property;
 
692
        object_class->set_property = gnome_xsettings_manager_set_property;
 
693
        object_class->constructor = gnome_xsettings_manager_constructor;
 
694
        object_class->dispose = gnome_xsettings_manager_dispose;
 
695
        object_class->finalize = gnome_xsettings_manager_finalize;
 
696
 
 
697
        g_type_class_add_private (klass, sizeof (GnomeXSettingsManagerPrivate));
 
698
}
 
699
 
 
700
static TranslationEntry *
 
701
find_translation_entry (const char *gconf_key)
 
702
{
 
703
        int i;
 
704
 
 
705
        for (i =0; i < G_N_ELEMENTS (translations); i++) {
 
706
                if (strcmp (translations[i].gconf_key, gconf_key) == 0) {
 
707
                        return &translations[i];
 
708
                }
 
709
        }
 
710
 
 
711
        return NULL;
 
712
}
 
713
 
 
714
static void
 
715
xsettings_callback (GConfClient           *client,
 
716
                    guint                  cnxn_id,
 
717
                    GConfEntry            *entry,
 
718
                    GnomeXSettingsManager *manager)
 
719
{
 
720
        TranslationEntry *trans;
 
721
        int               i;
 
722
 
 
723
        trans = find_translation_entry (entry->key);
 
724
        if (trans == NULL) {
 
725
                return;
 
726
        }
 
727
 
 
728
        process_value (manager, trans, entry->value);
 
729
 
 
730
        for (i = 0; manager->priv->managers [i]; i++) {
 
731
                xsettings_manager_set_string (manager->priv->managers [i],
 
732
                                              "Net/FallbackIconTheme",
 
733
                                              "gnome");
 
734
        }
 
735
 
 
736
        for (i = 0; manager->priv->managers [i]; i++) {
 
737
                xsettings_manager_notify (manager->priv->managers [i]);
 
738
        }
 
739
}
 
740
 
 
741
static void
 
742
register_config_callback (GnomeXSettingsManager  *manager,
 
743
                          const char             *path,
 
744
                          GConfClientNotifyFunc   func)
 
745
{
 
746
        GConfClient *client;
 
747
 
 
748
        client = gconf_client_get_default ();
 
749
 
 
750
        gconf_client_add_dir (client, path, GCONF_CLIENT_PRELOAD_NONE, NULL);
 
751
        gconf_client_notify_add (client, path, func, manager, NULL, NULL);
 
752
 
 
753
        g_object_unref (client);
 
754
}
 
755
 
 
756
static void
 
757
terminate_cb (void *data)
 
758
{
 
759
        gboolean *terminated = data;
 
760
 
 
761
        if (*terminated) {
 
762
                return;
 
763
        }
 
764
 
 
765
        *terminated = TRUE;
 
766
 
 
767
        gtk_main_quit ();
 
768
}
 
769
 
 
770
static void
 
771
gnome_xsettings_manager_init (GnomeXSettingsManager *manager)
 
772
{
 
773
        GdkDisplay *display;
 
774
        int         i;
 
775
        int         n_screens;
 
776
        gboolean    res;
 
777
        gboolean    terminated;
 
778
 
 
779
        manager->priv = GNOME_XSETTINGS_MANAGER_GET_PRIVATE (manager);
 
780
 
 
781
        display = gdk_display_get_default ();
 
782
        n_screens = gdk_display_get_n_screens (display);
 
783
 
 
784
        res = xsettings_manager_check_running (gdk_x11_display_get_xdisplay (display),
 
785
                                               gdk_screen_get_number (gdk_screen_get_default ()));
 
786
        if (res) {
 
787
                g_error ("You can only run one xsettings manager at a time; exiting\n");
 
788
                exit (1);
 
789
        }
 
790
 
 
791
        manager->priv->managers = g_new (XSettingsManager *, n_screens + 1);
 
792
 
 
793
        terminated = FALSE;
 
794
        for (i = 0; i < n_screens; i++) {
 
795
                GdkScreen *screen;
 
796
 
 
797
                screen = gdk_display_get_screen (display, i);
 
798
 
 
799
                manager->priv->managers [i] = xsettings_manager_new (gdk_x11_display_get_xdisplay (display),
 
800
                                                                     gdk_screen_get_number (screen),
 
801
                                                                     terminate_cb,
 
802
                                                                     &terminated);
 
803
                if (! manager->priv->managers [i]) {
 
804
                        g_error ("Could not create xsettings manager for screen %d!\n", i);
 
805
                        exit (1);
 
806
                }
 
807
        }
 
808
 
 
809
        manager->priv->managers [i] = NULL;
 
810
 
 
811
        register_config_callback (manager, "/desktop/gnome/peripherals/mouse", (GConfClientNotifyFunc)xsettings_callback);
 
812
        register_config_callback (manager, "/desktop/gtk", (GConfClientNotifyFunc)xsettings_callback);
 
813
        register_config_callback (manager, "/desktop/gnome/interface", (GConfClientNotifyFunc)xsettings_callback);
 
814
 
 
815
#ifdef HAVE_XFT2
 
816
        register_config_callback (manager, FONT_RENDER_DIR, (GConfClientNotifyFunc)xft_callback);
 
817
#endif /* HAVE_XFT2 */
 
818
 
 
819
}
 
820
 
 
821
static void
 
822
gnome_xsettings_manager_finalize (GObject *object)
 
823
{
 
824
        GnomeXSettingsManager *xsettings_manager;
 
825
 
 
826
        g_return_if_fail (object != NULL);
 
827
        g_return_if_fail (GNOME_IS_XSETTINGS_MANAGER (object));
 
828
 
 
829
        xsettings_manager = GNOME_XSETTINGS_MANAGER (object);
 
830
 
 
831
        g_return_if_fail (xsettings_manager->priv != NULL);
 
832
 
 
833
        G_OBJECT_CLASS (gnome_xsettings_manager_parent_class)->finalize (object);
 
834
}
 
835
 
 
836
GnomeXSettingsManager *
 
837
gnome_xsettings_manager_new (void)
 
838
{
 
839
        if (manager_object != NULL) {
 
840
                g_object_ref (manager_object);
 
841
        } else {
 
842
                manager_object = g_object_new (GNOME_TYPE_XSETTINGS_MANAGER, NULL);
 
843
                g_object_add_weak_pointer (manager_object,
 
844
                                           (gpointer *) &manager_object);
 
845
        }
 
846
 
 
847
        return GNOME_XSETTINGS_MANAGER (manager_object);
 
848
}