diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | configure.ac.in | 3 | ||||
-rw-r--r-- | xfsettingsd/Makefile.am | 22 | ||||
-rw-r--r-- | xfsettingsd/main.c | 191 | ||||
-rw-r--r-- | xfsettingsd/registry.c | 582 | ||||
-rw-r--r-- | xfsettingsd/registry.h | 86 |
7 files changed, 885 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index b5793ff..841c15c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,7 @@ SUBDIRS = \ common \ xfconf \ xfconfd \ + xfsettingsd \ po \ docs \ tests @@ -24,6 +24,7 @@ changes? load it and send PropertyChanged for all properties? that could be very bad. * separate XSETTINGS daemon that reads values from xfconfd + - add multi-screen support * libxfce4mcs-client dummy implementation that forwards to libxfconf * cmdline get/set/query tool so the config store can be scriptable diff --git a/configure.ac.in b/configure.ac.in index 18b0baa..748ef3c 100644 --- a/configure.ac.in +++ b/configure.ac.in @@ -64,7 +64,7 @@ dnl XDT_CHECK_LIBX11_REQUIRE dnl required XDT_CHECK_PACKAGE([GLIB], [gobject-2.0], [2.8.0]) -dnl XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0]) +XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0]) XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.4.0]) dnl XDT_CHECK_PACKAGE([LIBXFCEGUI4], [libxfcegui4-1.0], [4.4.0]) XDT_CHECK_PACKAGE([DBUS], [dbus-1], [1.0.0]) @@ -167,4 +167,5 @@ tests/Makefile xfconf/Makefile xfconf/libxfconf-0.pc xfconfd/Makefile +xfsettingsd/Makefile ]) diff --git a/xfsettingsd/Makefile.am b/xfsettingsd/Makefile.am new file mode 100644 index 0000000..d1841ed --- /dev/null +++ b/xfsettingsd/Makefile.am @@ -0,0 +1,22 @@ +bin_PROGRAMS = xfsettingsd + +xfsettingsd_SOURCES = \ + main.c \ + registry.c registry.h + +xfsettingsd_CFLAGS = \ + $(GTK_CFLAGS) \ + $(GLIB_CFLAGS) \ + $(DBUS_GLIB_CFLAGS) \ + -DDATADIR=\"$(datadir)\" \ + -DSRCDIR=\"$(top_srcdir)\" \ + -DLOCALEDIR=\"$(localedir)\" + +xfsettingsd_LDADD = \ + $(top_builddir)/xfconf/libxfconf-0.la \ + $(GTK_LIBS) \ + $(GLIB_LIBS) \ + $(DBUS_GLIB_LIBS) + +INCLUDES = \ + -I${top_srcdir} diff --git a/xfsettingsd/main.c b/xfsettingsd/main.c new file mode 100644 index 0000000..62f0ff9 --- /dev/null +++ b/xfsettingsd/main.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2008 Stephan Arts <stephan@xfce.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <config.h> +#include <X11/Xlib.h> + +#include <glib.h> + +#if defined(GETTEXT_PACKAGE) +#include <glib/gi18n-lib.h> +#else +#include <glib/gi18n.h> +#endif + +#include <gtk/gtk.h> +#include <gdk/gdkx.h> + +#include <xfconf/xfconf.h> + +#include "registry.h" + +#define XF_DEBUG(str) \ + if (debug) g_print (str) + +gboolean version = FALSE; +gboolean force_replace = FALSE; +gboolean running = FALSE; +gboolean debug = FALSE; + +static GOptionEntry entries[] = +{ + { "version", 'v', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &version, + N_("Version information"), + NULL + }, + { "verbose", 'V', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &version, + N_("Verbose output"), + NULL + }, + { "force", 'f', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &force_replace, + N_("Force replace existing any xsettings daemon"), + NULL + }, + { "debug", 'd', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &debug, + N_("Start in debug mode (don't fork to the background)"), + NULL + }, + { NULL } +}; + + +GdkFilterReturn +manager_event_filter (GdkXEvent *xevent, + GdkEvent *event, + gpointer data) +{ + if (FALSE) + { + return GDK_FILTER_REMOVE; + } + else + { + return GDK_FILTER_CONTINUE; + } +} + +/** + * settings_daemon_check_running: + * @display: X11 Display object + * @screen: X11 Screen number + * + * Return value: TRUE if an XSETTINGS daemon is already running + */ +gboolean +settings_daemon_check_running (Display *display, gint screen) +{ + Atom atom; + gchar buffer[256]; + + g_sprintf(buffer, "_XSETTINGS_S%d", screen); + atom = XInternAtom((Display *)display, buffer, False); + + if (XGetSelectionOwner((Display *)display, atom)) + { + return TRUE; + } + else + return FALSE; +} + +int +main(int argc, char **argv) +{ + Atom selection_atom; + Atom xsettings_atom; + Atom manager_atom; + + GError *cli_error = NULL; + + #ifdef ENABLE_NLS + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + #endif + + if(!gtk_init_with_args(&argc, &argv, _(""), entries, PACKAGE, &cli_error)) + { + if (cli_error != NULL) + { + g_print (_("%s: %s\nTry %s --help to see a full list of available command line options.\n"), PACKAGE, cli_error->message, PACKAGE_NAME); + g_error_free (cli_error); + return 1; + } + } + + if(version) + { + g_print("%s\n", PACKAGE_STRING); + return 0; + } + + xfconf_init(NULL); + + gint screen = DefaultScreen(gdk_display); + + Window window = 0; + + running = settings_daemon_check_running(GDK_DISPLAY(), DefaultScreen(GDK_DISPLAY())); + + if (running) + { + XF_DEBUG("XSETTINGS Daemon running\n"); + if (force_replace) + { + XF_DEBUG("Replacing XSETTINGS daemon\n"); + } + else + { + XF_DEBUG("Aborting...\n"); + return 1; + } + } + + if ((running && force_replace) || (!running)) + { + XF_DEBUG("Initializing...\n"); + + XfconfChannel *channel = xfconf_channel_new("xsettings"); + + XSettingsRegistry *registry = xsettings_registry_new(channel, gdk_display, screen); + + xsettings_registry_load(registry, debug); + + xsettings_registry_notify(registry); + } + + gdk_window_add_filter(NULL, manager_event_filter, NULL); + + if(!debug) /* If not in debug mode, fork to background */ + { + if(!fork()) + { + gtk_main(); + + XDestroyWindow (gdk_display, window); + xfconf_shutdown(); + } + } + else + { + gtk_main(); + + XDestroyWindow (gdk_display, window); + xfconf_shutdown(); + } +} diff --git a/xfsettingsd/registry.c b/xfsettingsd/registry.c new file mode 100644 index 0000000..c4e316a --- /dev/null +++ b/xfsettingsd/registry.c @@ -0,0 +1,582 @@ +/* + * Copyright (c) 2008 Stephan Arts <stephan@xfce.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Based on the XSETTINGS spec written by Owen Taylor + */ + +#include <config.h> +#include <X11/Xlib.h> +#include <X11/Xmd.h> + +#include <glib.h> + +#if defined(GETTEXT_PACKAGE) +#include <glib/gi18n-lib.h> +#else +#include <glib/gi18n.h> +#endif + +#include <gtk/gtk.h> +#include <gdk/gdkx.h> + +#include <string.h> + +#include <xfconf/xfconf.h> + +#include "registry.h" + +#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1))) + +#define XSETTINGS_DEBUG(str) \ + if (debug) g_print ("%s", str) +#define XSETTINGS_DEBUG_CREATE(str) \ + if (debug) g_print ("Creating Property: '%s'\n", str) +#define XSETTINGS_DEBUG_LOAD(str) \ + if (debug) g_print ("Loading Property: '%s'\n", str) + +G_DEFINE_TYPE(XSettingsRegistry, xsettings_registry, G_TYPE_OBJECT); + +struct _XSettingsRegistryPriv +{ + XSettingsRegistryEntry **properties; + + gint serial; + gint last_change_serial; + + /* props */ + XfconfChannel *channel; + gint screen; + Display *display; + Window window; + Atom xsettings_atom; +}; + +static void xsettings_registry_set_property(GObject*, guint, const GValue*, GParamSpec*); +static void xsettings_registry_get_property(GObject*, guint, GValue*, GParamSpec*); + +static void +cb_xsettings_registry_channel_property_changed(XfconfChannel *channel, const gchar *property_name, XSettingsRegistry *registry); +static Bool +timestamp_predicate (Display *display, XEvent *xevent, XPointer arg); + +static XSettingsRegistryEntry * +xsettings_registry_entry_new_string(const gchar *name, const gchar *value); +static XSettingsRegistryEntry * +xsettings_registry_entry_new_int(const gchar *name, gint value); +static XSettingsRegistryEntry * +xsettings_registry_entry_new_bool(const gchar *name, gboolean value); + +#define XSETTINGS_REGISTRY_SIZE 24 + +enum { + XSETTINGS_REGISTRY_PROPERTY_CHANNEL = 1, + XSETTINGS_REGISTRY_PROPERTY_DISPLAY, + XSETTINGS_REGISTRY_PROPERTY_SCREEN, + XSETTINGS_REGISTRY_PROPERTY_XSETTINGS_ATOM, + XSETTINGS_REGISTRY_PROPERTY_WINDOW +}; + +void +xsettings_registry_class_init(XSettingsRegistryClass *reg_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS(reg_class); + GParamSpec *pspec; + + object_class->set_property = xsettings_registry_set_property; + object_class->get_property = xsettings_registry_get_property; + + + pspec = g_param_spec_object("channel", NULL, NULL, XFCONF_TYPE_CHANNEL, G_PARAM_READABLE|G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(object_class, XSETTINGS_REGISTRY_PROPERTY_CHANNEL, pspec); + + pspec = g_param_spec_int("screen", NULL, NULL, -1, 65535, -1, G_PARAM_READABLE|G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(object_class, XSETTINGS_REGISTRY_PROPERTY_SCREEN, pspec); + + pspec = g_param_spec_pointer("display", NULL, NULL, G_PARAM_READABLE|G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(object_class, XSETTINGS_REGISTRY_PROPERTY_DISPLAY, pspec); + + pspec = g_param_spec_long("xsettings_atom", NULL, NULL, G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE|G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(object_class, XSETTINGS_REGISTRY_PROPERTY_XSETTINGS_ATOM, pspec); + + pspec = g_param_spec_long("window", NULL, NULL, G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE|G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property(object_class, XSETTINGS_REGISTRY_PROPERTY_WINDOW, pspec); + +} + +void +xsettings_registry_init(XSettingsRegistry *registry) +{ + registry->priv = g_new0(XSettingsRegistryPriv, 1); + registry->priv->properties = g_new0(XSettingsRegistryEntry *, XSETTINGS_REGISTRY_SIZE); + + gint i = XSETTINGS_REGISTRY_SIZE; + /* Net settings */ + registry->priv->properties[--i] = xsettings_registry_entry_new_int("Net/DoubleClickTime", 250); + registry->priv->properties[--i] = xsettings_registry_entry_new_int("Net/DoubleClickDistance", 5); + registry->priv->properties[--i] = xsettings_registry_entry_new_int("Net/DndDragThreshold", 8); + registry->priv->properties[--i] = xsettings_registry_entry_new_bool("Net/CursorBlink", TRUE); + registry->priv->properties[--i] = xsettings_registry_entry_new_int("Net/CursorBlinkTime", 1200); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Net/ThemeName", "Default"); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Net/IconThemeName", "hicolor"); + /* Xft settings */ + registry->priv->properties[--i] = xsettings_registry_entry_new_int("Xft/Antialias", -1); + registry->priv->properties[--i] = xsettings_registry_entry_new_int("Xft/Hinting", -1); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Xft/HintStyle", "hintnone"); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Xft/RGBA", "none"); + registry->priv->properties[--i] = xsettings_registry_entry_new_int("Xft/DPI", -1); + /* GTK settings */ + registry->priv->properties[--i] = xsettings_registry_entry_new_bool("Gtk/CanChangeAccels", FALSE); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Gtk/ColorPalette", + "black:white:gray50:red:purple:blue:light " + "blue:green:yellow:orange:lavender:brown:goldenrod4:dodger " + "blue:pink:light green:gray10:gray30:gray75:gray90"); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Gtk/FontName", "Sans 10"); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Gtk/IconSizes", NULL); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Gtk/KeyThemeName", NULL); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Gtk/ToolbarStyle", "Icons"); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Gtk/ToolbarIconSize", "LARGE_TOOLBAR"); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Gtk/IMPreeditStyle", ""); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Gtk/IMStatusStyle", ""); + registry->priv->properties[--i] = xsettings_registry_entry_new_bool("Gtk/MenuImages", TRUE); + registry->priv->properties[--i] = xsettings_registry_entry_new_bool("Gtk/ButtonImages", TRUE); + registry->priv->properties[--i] = xsettings_registry_entry_new_string("Gtk/MenuBarAccel", "F10"); + +#ifdef DEBUG + if (i != 0) + g_critical ("XSETTINGS_REGISTRY_SIZE != number of registry items"); +#endif + +} + +static void +cb_xsettings_registry_channel_property_changed(XfconfChannel *channel, const gchar *name, XSettingsRegistry *registry) +{ + gint i; + + for (i = 0; i < XSETTINGS_REGISTRY_SIZE; ++i) + { + XSettingsRegistryEntry *entry = registry->priv->properties[i]; + if (!strcmp(entry->name, &name[1])) + { + switch (G_VALUE_TYPE(entry->value)) + { + case G_TYPE_INT: + g_value_set_int(entry->value, xfconf_channel_get_int(channel, name, g_value_get_int(entry->value))); + break; + case G_TYPE_STRING: + g_value_set_string(entry->value, xfconf_channel_get_string(channel, name, g_value_get_string(entry->value))); + break; + case G_TYPE_BOOLEAN: + g_value_set_boolean(entry->value, xfconf_channel_get_bool(channel, name, g_value_get_boolean(entry->value))); + break; + } + } + } + xsettings_registry_notify(registry); +} + +void +xsettings_registry_notify(XSettingsRegistry *registry) +{ + registry->priv->last_change_serial = registry->priv->serial; + + XSettingsRegistryEntry *entry = NULL; + + gint buf_len = 12; + gint i; + + /** Calculate buffer size */ + for(i = 0; i < XSETTINGS_REGISTRY_SIZE; ++i) + { + entry = registry->priv->properties[i]; + buf_len += 8 + XSETTINGS_PAD(strlen(entry->name), 4); + switch (G_VALUE_TYPE(entry->value)) + { + case G_TYPE_INT: + case G_TYPE_BOOLEAN: + buf_len += 4; + break; + case G_TYPE_STRING: + { + buf_len += 4; + const gchar *value = g_value_get_string(entry->value); + if(value) + { + buf_len += XSETTINGS_PAD(strlen(value), 4); + } + + } + break; + case G_TYPE_UINT64: + buf_len += 8; + break; + } + } + + guchar *buffer = NULL; + guchar *pos = buffer = g_new0(guchar, buf_len); + + *(CARD32 *)pos = LSBFirst; + pos +=4; + + *(CARD32 *)pos = registry->priv->serial++; + pos += 4; + + *(CARD32 *)pos = XSETTINGS_REGISTRY_SIZE; + pos += 4; + + /** Fill the buffer */ + for(i = 0; i < XSETTINGS_REGISTRY_SIZE; ++i) + { + entry = registry->priv->properties[i]; + + gint name_len = XSETTINGS_PAD(strlen(entry->name), 4); + gint value_len; + + switch (G_VALUE_TYPE(entry->value)) + { + case G_TYPE_INT: + case G_TYPE_BOOLEAN: + *pos++ = 0; + break; + case G_TYPE_STRING: + *pos++ = 1; // String + { + const gchar *value = g_value_get_string(entry->value); + if(value) + { + value_len = XSETTINGS_PAD(strlen(value), 4); + } + else + { + value_len = 0; + } + } + break; + case G_TYPE_UINT64: /* Color is a 64-bits value */ + *pos++ = 2; + break; + } + *pos++ = 0; + + gint str_length = strlen(entry->name); + *(CARD16 *)pos = str_length; + pos += 2; + memcpy (pos, entry->name, str_length); + name_len -= str_length; + pos += str_length; + + while(name_len > 0) + { + *(pos++) = 0; + name_len--; + } + + *(CARD32 *)pos = registry->priv->last_change_serial; + pos+= 4; + + switch (G_VALUE_TYPE(entry->value)) + { + case G_TYPE_STRING: + { + const gchar *val = g_value_get_string(entry->value); + + if (val) + { + *(CARD32 *)pos = strlen(val); + pos += 4; + + memcpy (pos, val, strlen(val)); + pos += strlen(val); + value_len -= strlen(val); + } + else + { + *(CARD32 *)pos = 0; + pos += 4; + } + } + while(value_len > 0) + { + *(pos++) = 0; + value_len--; + } + break; + case G_TYPE_INT: + *(CARD32 *)pos = g_value_get_int(entry->value); + pos += 4; + break; + case G_TYPE_BOOLEAN: + *(CARD32 *)pos = g_value_get_boolean(entry->value); + pos += 4; + break; + case G_TYPE_UINT64: + + pos += 8; + break; + } + + } + + XChangeProperty(registry->priv->display, + registry->priv->window, + registry->priv->xsettings_atom, + registry->priv->xsettings_atom, + 8, PropModeReplace, buffer, buf_len); + + registry->priv->last_change_serial = registry->priv->serial; +} + +static XSettingsRegistryEntry * +xsettings_registry_entry_new_string(const gchar *name, const gchar *value) +{ + XSettingsRegistryEntry *entry = g_new0(XSettingsRegistryEntry, 1); + entry->name = g_strdup(name); + + entry->value = g_new0(GValue, 1); + entry->value = g_value_init(entry->value, G_TYPE_STRING); + g_value_set_string(entry->value, value); + + return entry; +} + +static XSettingsRegistryEntry * +xsettings_registry_entry_new_int(const gchar *name, gint value) +{ + XSettingsRegistryEntry *entry = g_new0(XSettingsRegistryEntry, 1); + entry->name = g_strdup(name); + entry->value = g_new0(GValue, 1); + entry->value = g_value_init(entry->value, G_TYPE_INT); + g_value_set_int(entry->value, value); + + return entry; +} + +static XSettingsRegistryEntry * +xsettings_registry_entry_new_bool(const gchar *name, gboolean value) +{ + XSettingsRegistryEntry *entry = g_new0(XSettingsRegistryEntry, 1); + entry->name = g_strdup(name); + + entry->value = g_new0(GValue, 1); + entry->value = g_value_init(entry->value, G_TYPE_BOOLEAN); + g_value_set_boolean(entry->value, value); + + return entry; +} + +XSettingsRegistry * +xsettings_registry_new (XfconfChannel *channel, Display *dpy, gint screen) +{ + Atom xsettings_atom = XInternAtom(dpy, "_XSETTINGS_SETTINGS", True); + + Window window = 0; + + window = XCreateSimpleWindow (dpy, + RootWindow (dpy, screen), + 0, 0, 10, 10, 0, + WhitePixel (dpy, screen), + WhitePixel (dpy, screen)); + if (!window) + { + g_critical( "no window"); + return NULL; + } + + GObject *object = g_object_new(XSETTINGS_REGISTRY_TYPE, + "channel", channel, + "display", dpy, + "screen", screen, + "xsettings_atom", xsettings_atom, + "window", window, + NULL); + gchar buffer[256]; + unsigned char c = 'a'; + TimeStampInfo info; + Atom timestamp_atom; + XEvent xevent; + + g_sprintf(buffer, "_XSETTINGS_S%d", screen); + Atom selection_atom = XInternAtom(dpy, buffer, True); + Atom manager_atom = XInternAtom(dpy, "MANAGER", True); + + info.timestamp_prop_atom = XInternAtom(dpy, "_TIMESTAMP_PROP", False); + info.window = window; + + XSelectInput (dpy, window, PropertyChangeMask); + + XChangeProperty (dpy, window, + info.timestamp_prop_atom, info.timestamp_prop_atom, + 8, PropModeReplace, &c, 1); + + XIfEvent (dpy, &xevent, + timestamp_predicate, (XPointer)&info); + + XSetSelectionOwner (dpy, selection_atom, + window, xevent.xproperty.time); + + if (XGetSelectionOwner (dpy, selection_atom) == + window) + { + XClientMessageEvent xev; + + xev.type = ClientMessage; + xev.window = RootWindow (dpy, screen); + xev.message_type = manager_atom; + xev.format = 32; + xev.data.l[0] = xevent.xproperty.time; + xev.data.l[1] = selection_atom; + xev.data.l[2] = window; + xev.data.l[3] = 0; /* manager specific data */ + xev.data.l[4] = 0; /* manager specific data */ + + XSendEvent (dpy, RootWindow (dpy, screen), + False, StructureNotifyMask, (XEvent *)&xev); + } + else + { + g_debug("fail"); + } + + return XSETTINGS_REGISTRY(object); +} + +static void +xsettings_registry_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *p_spec) +{ + switch(property_id) + { + case XSETTINGS_REGISTRY_PROPERTY_CHANNEL: + if (XSETTINGS_REGISTRY(object)->priv->channel) + { + XfconfChannel *channel = XSETTINGS_REGISTRY(object)->priv->channel; + + g_signal_handlers_disconnect_by_func(G_OBJECT(channel), (GCallback)cb_xsettings_registry_channel_property_changed, object); + XSETTINGS_REGISTRY(object)->priv->channel = NULL; + } + + XSETTINGS_REGISTRY(object)->priv->channel = g_value_get_object(value); + + if (XSETTINGS_REGISTRY(object)->priv->channel) + { + XfconfChannel *channel = XSETTINGS_REGISTRY(object)->priv->channel; + + g_signal_connect(G_OBJECT(channel), "property-changed", (GCallback)cb_xsettings_registry_channel_property_changed, object); + } + break; + case XSETTINGS_REGISTRY_PROPERTY_SCREEN: + XSETTINGS_REGISTRY(object)->priv->screen = g_value_get_int(value); + break; + case XSETTINGS_REGISTRY_PROPERTY_DISPLAY: + XSETTINGS_REGISTRY(object)->priv->display = g_value_get_pointer(value); + break; + case XSETTINGS_REGISTRY_PROPERTY_XSETTINGS_ATOM: + XSETTINGS_REGISTRY(object)->priv->xsettings_atom = g_value_get_long(value); + break; + case XSETTINGS_REGISTRY_PROPERTY_WINDOW: + XSETTINGS_REGISTRY(object)->priv->window = g_value_get_long(value); + break; + } + +} + +static void +xsettings_registry_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *p_spec) +{ + switch(property_id) + { + case XSETTINGS_REGISTRY_PROPERTY_CHANNEL: + g_value_set_object(value, XSETTINGS_REGISTRY(object)->priv->channel); + break; + case XSETTINGS_REGISTRY_PROPERTY_SCREEN: + g_value_set_int(value, XSETTINGS_REGISTRY(object)->priv->screen); + break; + case XSETTINGS_REGISTRY_PROPERTY_DISPLAY: + g_value_set_pointer(value, XSETTINGS_REGISTRY(object)->priv->display); + break; + case XSETTINGS_REGISTRY_PROPERTY_XSETTINGS_ATOM: + g_value_set_long(value, XSETTINGS_REGISTRY(object)->priv->xsettings_atom); + break; + case XSETTINGS_REGISTRY_PROPERTY_WINDOW: + g_value_set_long(value, XSETTINGS_REGISTRY(object)->priv->window); + break; + } + +} + +static Bool +timestamp_predicate (Display *display, + XEvent *xevent, + XPointer arg) +{ + TimeStampInfo *info = (TimeStampInfo *)arg; + + if (xevent->type == PropertyNotify && + xevent->xproperty.window == info->window && + xevent->xproperty.atom == info->timestamp_prop_atom) + return True; + + return False; +} + +gboolean +xsettings_registry_load(XSettingsRegistry *registry, gboolean debug) +{ + gint i; + XfconfChannel *channel = registry->priv->channel; + + for(i = 0; i < XSETTINGS_REGISTRY_SIZE ; ++i) + { + XSettingsRegistryEntry *entry = registry->priv->properties[i]; + + gchar *name = g_strconcat("/", entry->name, NULL); + + if (xfconf_channel_has_property(channel, name) == TRUE) + { + XSETTINGS_DEBUG_LOAD(entry->name); + switch (G_VALUE_TYPE(entry->value)) + { + case G_TYPE_INT: + g_value_set_int(entry->value, xfconf_channel_get_int(channel, name, g_value_get_int(entry->value))); + break; + case G_TYPE_STRING: + g_value_set_string(entry->value, xfconf_channel_get_string(channel, name, g_value_get_string(entry->value))); + break; + case G_TYPE_BOOLEAN: + g_value_set_boolean(entry->value, xfconf_channel_get_bool(channel, name, g_value_get_boolean(entry->value))); + break; + } + } + else + { + XSETTINGS_DEBUG_CREATE(entry->name); + + if(xfconf_channel_set_property(channel, name, entry->value)) + { + XSETTINGS_DEBUG("... OK\n"); + } + else + { + XSETTINGS_DEBUG("... FAIL\n"); + } + } + + g_free(name); + + } +} diff --git a/xfsettingsd/registry.h b/xfsettingsd/registry.h new file mode 100644 index 0000000..6a0a675 --- /dev/null +++ b/xfsettingsd/registry.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2008 Stephan Arts <stephan@xfce.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __XSETTINGS_REGISTRY_H__ +#define __XSETTINGS_REGISTRY_H__ + +typedef struct _XSettingsRegistryEntry XSettingsRegistryEntry; + +struct _XSettingsRegistryEntry { + gchar *name; + GValue *value; + Atom atom; +}; + +#define XSETTINGS_REGISTRY_TYPE xsettings_registry_get_type() + +#define XSETTINGS_REGISTRY(obj) ( \ + G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + XSETTINGS_REGISTRY_TYPE, \ + XSettingsRegistry)) + +#define XSETTINGS_IS_REGISTRY(obj) ( \ + G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + XSETTINGS_REGISTRY_TYPE)) + +#define XSETTINGS_REGISTRY_CLASS(class) ( \ + G_TYPE_CHECK_CLASS_CAST ((class), \ + XSETTINGS_REGISTRY_TYPE, \ + XSettingsRegistryClass)) + +#define XSETTINGS_IS_REGISTRY_CLASS(class) ( \ + G_TYPE_CHECK_CLASS_TYPE ((class), \ + XSETTINGS_REGISTRY_TYPE)) + +#define XSETTINGS_REGISTRY_GET_CLASS(obj) ( \ + G_TYPE_INSTANCE_GET_CLASS ((obj), \ + XSETTINGS_REGISTRY_TYPE, \ + XSettingsRegistryClass)) + +typedef struct +{ + Window window; + Atom timestamp_prop_atom; +} TimeStampInfo; + + +typedef struct _XSettingsRegistryPriv XSettingsRegistryPriv; +typedef struct _XSettingsRegistry XSettingsRegistry; + +struct _XSettingsRegistry { + GObject parent; + XSettingsRegistryPriv *priv; +}; + +typedef struct _XSettingsRegistryClass XSettingsRegistryClass; + +struct _XSettingsRegistryClass { + GObjectClass parent_class; +}; + +GType xsettings_registry_get_type(); + +XSettingsRegistry * +xsettings_registry_new (XfconfChannel *channel, Display *dpy, gint screen); + +gboolean +xsettings_registry_load(XSettingsRegistry *registry, gboolean debug); +void +xsettings_registry_notify(XSettingsRegistry *registry); + +#endif /* __XSETTINGS_REGISTRY_H__ */ |