2009-06-29 12:07:10 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
#include "shell-gconf.h"
|
|
|
|
|
|
|
|
#include <gconf/gconf-client.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ShellGConf:
|
|
|
|
*
|
|
|
|
* A wrapper around #GConfClient that cleans up some of its
|
|
|
|
* non-gjs-bindable bits and makes a few gnome-shell-specific
|
|
|
|
* assumptions.
|
|
|
|
*
|
|
|
|
* For all #ShellGConf methods that take a GConf key path as an
|
|
|
|
* argument, you can pass either a full path (eg,
|
|
|
|
* "/desktop/gnome/shell/sidebar/visible"), or just a relative path
|
|
|
|
* starting from the root of the gnome-shell GConf key hierarchy (eg,
|
|
|
|
* "sidebar/visible").
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct _ShellGConf
|
|
|
|
{
|
|
|
|
GObject parent;
|
|
|
|
|
|
|
|
GConfClient *client;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (ShellGConf, shell_gconf, G_TYPE_OBJECT);
|
|
|
|
|
|
|
|
/* Signals */
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
CHANGED,
|
|
|
|
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
static guint shell_gconf_signals [LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
|
|
static void gconf_value_changed (GConfClient *client, const char *key,
|
|
|
|
GConfValue *new_value, gpointer user_data);
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_gconf_init (ShellGConf *gconf)
|
|
|
|
{
|
|
|
|
gconf->client = gconf_client_get_default ();
|
|
|
|
gconf_client_add_dir (gconf->client, SHELL_GCONF_DIR,
|
|
|
|
GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
|
|
|
|
g_signal_connect (gconf->client, "value_changed",
|
|
|
|
G_CALLBACK (gconf_value_changed), gconf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_gconf_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
ShellGConf *gconf = SHELL_GCONF (object);
|
|
|
|
|
|
|
|
g_signal_handlers_disconnect_by_func (gconf->client,
|
|
|
|
gconf_value_changed, gconf);
|
|
|
|
g_object_unref (gconf->client);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (shell_gconf_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shell_gconf_class_init (ShellGConfClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
gobject_class->finalize = shell_gconf_finalize;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ShellGConf::changed:
|
|
|
|
* @gconf: the #ShellGConf
|
|
|
|
*
|
|
|
|
* Emitted when a key in a watched directory is changed. The signal
|
|
|
|
* detail indicates which key changed. Eg, connect to
|
|
|
|
* "changed::sidebar/visible" to be notified when "sidebar/visible"
|
|
|
|
* changes. For gnome-shell's own GConf keys, the signal detail will
|
|
|
|
* be the relative path from the top of the gnome-shell GConf
|
|
|
|
* hierarchy ("/desktop/gnome/shell"). If you want to be notified
|
|
|
|
* about the value of a non-gnome-shell key, you must first call
|
|
|
|
* shell_gconf_watch_directory(), and then use the full GConf key path
|
|
|
|
* as the signal detail.
|
|
|
|
*/
|
|
|
|
shell_gconf_signals[CHANGED] =
|
|
|
|
g_signal_new ("changed",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
|
|
|
|
G_STRUCT_OFFSET (ShellGConfClass, changed),
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_get_default:
|
|
|
|
*
|
|
|
|
* Gets the default #ShellGConf
|
|
|
|
*
|
|
|
|
* Return value: (transfer none): the default #ShellGConf
|
|
|
|
*/
|
|
|
|
ShellGConf *
|
|
|
|
shell_gconf_get_default (void)
|
|
|
|
{
|
|
|
|
static ShellGConf *gconf = NULL;
|
|
|
|
|
|
|
|
if (!gconf)
|
|
|
|
gconf = g_object_new (SHELL_TYPE_GCONF, NULL);
|
|
|
|
|
|
|
|
return gconf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_watch_directory:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @directory: the path of a GConf directory to watch for changes in
|
|
|
|
*
|
|
|
|
* Adds @directory to the list of directories to watch; you must call
|
|
|
|
* this before connecting to #ShellGConf::changed for a key outside of
|
|
|
|
* the gnome-shell GConf tree.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
shell_gconf_watch_directory (ShellGConf *gconf, const char *directory)
|
|
|
|
{
|
|
|
|
gconf_client_add_dir (gconf->client, directory,
|
|
|
|
GCONF_CLIENT_PRELOAD_NONE, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gconf_value_changed (GConfClient *client, const char *key,
|
|
|
|
GConfValue *new_value, gpointer user_data)
|
|
|
|
{
|
|
|
|
ShellGConf *gconf = user_data;
|
|
|
|
GQuark detail;
|
|
|
|
|
|
|
|
if (g_str_has_prefix (key, SHELL_GCONF_DIR "/"))
|
|
|
|
key += strlen (SHELL_GCONF_DIR "/");
|
|
|
|
|
|
|
|
/* This will create a lot of junk quarks, but it's the best we
|
|
|
|
* can do with gjs's current callback support.
|
|
|
|
*/
|
|
|
|
detail = g_quark_from_string (key);
|
|
|
|
g_signal_emit (gconf, shell_gconf_signals[CHANGED], detail);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
resolve_key (const char *key)
|
|
|
|
{
|
|
|
|
if (*key == '/')
|
|
|
|
return g_strdup (key);
|
|
|
|
else
|
|
|
|
return g_build_filename (SHELL_GCONF_DIR, key, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define SIMPLE_GETTER(NAME, TYPE, GCONF_GETTER) \
|
|
|
|
TYPE \
|
|
|
|
NAME (ShellGConf *gconf, const char *key, GError **error) \
|
|
|
|
{ \
|
|
|
|
char *get_key = resolve_key (key); \
|
|
|
|
TYPE value; \
|
|
|
|
\
|
|
|
|
value = GCONF_GETTER (gconf->client, get_key, error); \
|
|
|
|
g_free (get_key); \
|
|
|
|
return value; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define LIST_GETTER(NAME, ELEMENT_TYPE) \
|
|
|
|
GSList * \
|
|
|
|
NAME (ShellGConf *gconf, const char *key, GError **error) \
|
|
|
|
{ \
|
|
|
|
char *get_key = resolve_key (key); \
|
|
|
|
GSList *value; \
|
|
|
|
\
|
|
|
|
value = gconf_client_get_list (gconf->client, get_key, \
|
|
|
|
ELEMENT_TYPE, error); \
|
|
|
|
g_free (get_key); \
|
|
|
|
return value; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_get_boolean:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Gets the value of @key, which must be boolean-valued.
|
|
|
|
*
|
|
|
|
* Return value: @key's value. If an error occurs, @error will be set
|
|
|
|
* and the return value is undefined.
|
|
|
|
**/
|
|
|
|
SIMPLE_GETTER(shell_gconf_get_boolean, gboolean, gconf_client_get_bool)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_get_int:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Gets the value of @key, which must be integer-valued.
|
|
|
|
*
|
|
|
|
* Return value: @key's value. If an error occurs, @error will be set
|
|
|
|
* and the return value is undefined.
|
|
|
|
**/
|
|
|
|
SIMPLE_GETTER(shell_gconf_get_int, int, gconf_client_get_int)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_get_float:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Gets the value of @key, which must be float-valued.
|
|
|
|
*
|
|
|
|
* Return value: @key's value. If an error occurs, @error will be set
|
|
|
|
* and the return value is undefined.
|
|
|
|
**/
|
|
|
|
SIMPLE_GETTER(shell_gconf_get_float, float, gconf_client_get_float)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_get_string:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Gets the value of @key, which must be string-valued.
|
|
|
|
*
|
|
|
|
* Return value: (transfer full): @key's value, or %NULL if an error
|
|
|
|
* occurs.
|
|
|
|
**/
|
|
|
|
SIMPLE_GETTER(shell_gconf_get_string, char *, gconf_client_get_string)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_get_boolean_list:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Gets the value of @key, which must be boolean-list-valued.
|
|
|
|
*
|
|
|
|
* Return value: (element-type gboolean) (transfer full): @key's
|
|
|
|
* value, or %NULL if an error occurs.
|
|
|
|
**/
|
|
|
|
LIST_GETTER(shell_gconf_get_boolean_list, GCONF_VALUE_BOOL)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_get_int_list:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Gets the value of @key, which must be integer-list-valued.
|
|
|
|
*
|
|
|
|
* Return value: (element-type int) (transfer full): @key's
|
|
|
|
* value, or %NULL if an error occurs.
|
|
|
|
**/
|
|
|
|
LIST_GETTER(shell_gconf_get_int_list, GCONF_VALUE_INT)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_get_float_list:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Gets the value of @key, which must be float-list-valued.
|
|
|
|
*
|
|
|
|
* Return value: (element-type float) (transfer full): @key's
|
|
|
|
* value, or %NULL if an error occurs.
|
|
|
|
**/
|
|
|
|
LIST_GETTER(shell_gconf_get_float_list, GCONF_VALUE_FLOAT)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_get_string_list:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Gets the value of @key, which must be string-list-valued.
|
|
|
|
*
|
|
|
|
* Return value: (element-type utf8) (transfer full): @key's
|
|
|
|
* value, or %NULL if an error occurs.
|
|
|
|
**/
|
|
|
|
LIST_GETTER(shell_gconf_get_string_list, GCONF_VALUE_STRING)
|
|
|
|
|
|
|
|
|
|
|
|
#define SIMPLE_SETTER(NAME, TYPE, GCONF_SETTER) \
|
|
|
|
void \
|
|
|
|
NAME (ShellGConf *gconf, const char *key, TYPE value, GError **error) \
|
|
|
|
{ \
|
|
|
|
char *set_key = resolve_key (key); \
|
|
|
|
\
|
|
|
|
GCONF_SETTER (gconf->client, set_key, value, error); \
|
|
|
|
g_free (set_key); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define LIST_SETTER(NAME, ELEMENT_TYPE) \
|
|
|
|
void \
|
|
|
|
NAME (ShellGConf *gconf, const char *key, \
|
|
|
|
GSList *value, GError **error) \
|
|
|
|
{ \
|
|
|
|
char *set_key = resolve_key (key); \
|
|
|
|
\
|
|
|
|
gconf_client_set_list (gconf->client, set_key, ELEMENT_TYPE, \
|
|
|
|
value, error); \
|
|
|
|
g_free (set_key); \
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_set_boolean:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @value: value to set @key to
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Sets the value of @key to @value.
|
|
|
|
**/
|
|
|
|
SIMPLE_SETTER(shell_gconf_set_boolean, gboolean, gconf_client_set_bool)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_set_int:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @value: value to set @key to
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Sets the value of @key to @value.
|
|
|
|
**/
|
|
|
|
SIMPLE_SETTER(shell_gconf_set_int, int, gconf_client_set_int)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_set_float:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @value: value to set @key to
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Sets the value of @key to @value.
|
|
|
|
**/
|
|
|
|
SIMPLE_SETTER(shell_gconf_set_float, float, gconf_client_set_float)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_set_string:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @value: value to set @key to
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Sets the value of @key to @value.
|
|
|
|
**/
|
|
|
|
SIMPLE_SETTER(shell_gconf_set_string, const char *, gconf_client_set_string)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_set_boolean_list:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
2009-10-16 10:40:42 -04:00
|
|
|
* @value: (transfer none) (element-type gboolean): value to set @key to
|
2009-06-29 12:07:10 -04:00
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Sets the value of @key to @value.
|
|
|
|
**/
|
|
|
|
LIST_SETTER(shell_gconf_set_boolean_list, GCONF_VALUE_BOOL)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_set_int_list:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
|
|
|
* @value: (transfer none): value to set @key to
|
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Sets the value of @key to @value.
|
|
|
|
**/
|
|
|
|
LIST_SETTER(shell_gconf_set_int_list, GCONF_VALUE_INT)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_set_float_list:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
2009-10-16 10:40:42 -04:00
|
|
|
* @value: (transfer none) (element-type float): value to set @key to
|
2009-06-29 12:07:10 -04:00
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Sets the value of @key to @value.
|
|
|
|
**/
|
|
|
|
LIST_SETTER(shell_gconf_set_float_list, GCONF_VALUE_FLOAT)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* shell_gconf_set_string_list:
|
|
|
|
* @gconf: a #ShellGConf
|
|
|
|
* @key: a GConf key (as described in the #ShellGConf docs)
|
2009-10-16 10:40:42 -04:00
|
|
|
* @value: (transfer none) (element-type utf8): value to set @key to
|
2009-06-29 12:07:10 -04:00
|
|
|
* @error: a #GError, which will be set on error
|
|
|
|
*
|
|
|
|
* Sets the value of @key to @value.
|
|
|
|
**/
|
|
|
|
LIST_SETTER(shell_gconf_set_string_list, GCONF_VALUE_STRING)
|