Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSayamindu Dasgupta <sayamindu@gmail.com>2010-01-31 09:20:21 (GMT)
committer Sayamindu Dasgupta <sayamindu@gmail.com>2010-01-31 09:20:21 (GMT)
commit2b2816622012be0b494b59330dc08587c5e27b14 (patch)
treec598a0c02b60ba08fa8191de2ab3db2ecc125115
Initial import
-rw-r--r--AUTHORS0
-rw-r--r--COPYING25
-rw-r--r--Makefile.am1
-rw-r--r--NEWS0
-rw-r--r--README4
-rwxr-xr-xautogen.sh23
-rw-r--r--configure.in17
-rw-r--r--src/Makefile.am10
-rw-r--r--src/sugar-settings-manager.c158
-rw-r--r--src/xsettings-common.c264
-rw-r--r--src/xsettings-common.h110
-rw-r--r--src/xsettings-manager.c425
-rw-r--r--src/xsettings-manager.h69
13 files changed, 1106 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/AUTHORS
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..e6b68ce
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,25 @@
+
+Copyright (c) 2001 Red Hat, Inc.
+ (c) 2010 One Laptop Per Child
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of Red Hat not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. Red Hat makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+
+RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Authors: Owen Taylor, Red Hat, Inc.
+ Sayamindu Dasgupta, One Laptop Per Child
+
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..af437a6
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/README b/README
new file mode 100644
index 0000000..17200cc
--- /dev/null
+++ b/README
@@ -0,0 +1,4 @@
+Settings manager daemon for Sugar Learning Environment.
+
+Based on sample xsettings-manager reference
+implementation from http://webcvs.freedesktop.org/xsettings/xsettings
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..0f0c5ed
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+PKG_NAME="sugar-settings-manager"
+
+(test -f $srcdir/configure.in) || {
+ echo -n "**Error**: Directory \"\`$srcdir\'\" does not look like the"
+ echo " top-level $PKG_NAME directory"
+ exit 1
+}
+
+which gnome-autogen.sh || {
+ echo "You need to install gnome-common from the GNOME CVS"
+ exit 1
+}
+
+REQUIRED_AUTOMAKE_VERSION=1.6
+export REQUIRED_AUTOMAKE_VERSION
+
+USE_GNOME2_MACROS=1 . gnome-autogen.sh
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..6c1030e
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,17 @@
+AC_PREREQ(2.52)
+
+AC_INIT(sugar-settings-manager, 0.1)
+AC_CONFIG_SRCDIR(src)
+AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
+AM_CONFIG_HEADER(config.h)
+
+AC_PROG_CC
+
+PKG_CHECK_MODULES(SSM, [gtk+-2.0 gconf-2.0])
+AC_SUBST(SSM_CFLAGS)
+AC_SUBST(SSM_LIBS)
+
+AC_OUTPUT([
+Makefile
+src/Makefile
+])
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..64a84fb
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,10 @@
+INCLUDES = $(SSM_CFLAGS)
+
+bin_PROGRAMS = sugar-settings-manager
+
+sugar_settings_manager_SOURCES = sugar-settings-manager.c \
+ xsettings-common.c \
+ xsettings-common.h \
+ xsettings-manager.c \
+ xsettings-manager.h
+sugar_settings_manager_LDADD = $(SSM_LIBS)
diff --git a/src/sugar-settings-manager.c b/src/sugar-settings-manager.c
new file mode 100644
index 0000000..37b93a1
--- /dev/null
+++ b/src/sugar-settings-manager.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2001 Red Hat, Inc.
+ * (c) 2010 One Laptop Per Child
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: Owen Taylor, Red Hat, Inc.
+ * Sayamindu Dasgupta <sayamindu@laptop.org>
+ *
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include <gconf/gconf-client.h>
+
+#include "xsettings-manager.h"
+
+#define SUGAR_FONT_DIR "/desktop/sugar/font"
+#define SUGAR_FONT_FACE_KEY "/desktop/sugar/font/default_face"
+#define SUGAR_FONT_SIZE_KEY "/desktop/sugar/font/default_size"
+
+/* See http://freedesktop.org/wiki/Specifications/XSettingsRegistry */
+#define XSETTINGS_REGISTRY_GTK_FONT_NAME "Gtk/FontName"
+
+XSettingsManager *manager;
+GConfClient *client;
+
+void terminate_cb()
+{
+ gtk_main_quit();
+}
+
+GdkFilterReturn
+manager_event_filter(GdkXEvent * xevent, GdkEvent * event, gpointer data)
+{
+ if (xsettings_manager_process_event(manager, (XEvent *) xevent))
+ return GDK_FILTER_REMOVE;
+ else
+ return GDK_FILTER_CONTINUE;
+}
+
+void update_font()
+{
+ gchar *font_face, *font_name;
+ gdouble font_size;
+
+ font_face = gconf_client_get_string(client, SUGAR_FONT_FACE_KEY, NULL);
+ if (!font_face)
+ return;
+
+ font_size = gconf_client_get_float(client, SUGAR_FONT_SIZE_KEY, NULL);
+ if (!font_size)
+ return;
+
+ font_name = g_strdup_printf("%s %f", font_face, font_size);
+
+ xsettings_manager_set_string(manager, XSETTINGS_REGISTRY_GTK_FONT_NAME,
+ font_name);
+ xsettings_manager_notify(manager);
+}
+
+void
+font_face_changed_callback(GConfClient * client,
+ guint cnxn_id,
+ GConfEntry * entry, gpointer user_data)
+{
+ if (entry->value == NULL) {
+ return;
+ } else {
+ if (entry->value->type == GCONF_VALUE_STRING) {
+ update_font();
+ } else {
+ return;
+ }
+ }
+}
+
+void
+font_size_changed_callback(GConfClient * client,
+ guint cnxn_id,
+ GConfEntry * entry, gpointer user_data)
+{
+ if (entry->value == NULL) {
+ return;
+ } else {
+ if (entry->value->type == GCONF_VALUE_FLOAT) {
+ update_font();
+ } else {
+ return;
+ }
+ }
+}
+
+
+void setup_font()
+{
+ client = gconf_client_get_default();
+ gconf_client_add_dir(client,
+ SUGAR_FONT_DIR, GCONF_CLIENT_PRELOAD_NONE, NULL);
+
+ gconf_client_notify_add(client, SUGAR_FONT_FACE_KEY,
+ (GConfClientNotifyFunc)
+ font_face_changed_callback, NULL, NULL, NULL);
+
+ gconf_client_notify_add(client, SUGAR_FONT_SIZE_KEY,
+ (GConfClientNotifyFunc)
+ font_size_changed_callback, NULL, NULL, NULL);
+
+ update_font();
+}
+
+int main(int argc, char **argv)
+{
+ gtk_init(&argc, &argv);
+
+ if (xsettings_manager_check_running
+ (gdk_display, DefaultScreen(gdk_display))) {
+ fprintf(stderr,
+ "Could not create manager! Manager already running.\n");
+ exit(1);
+ }
+
+ manager =
+ xsettings_manager_new(gdk_display, DefaultScreen(gdk_display),
+ terminate_cb, NULL);
+ if (!manager) {
+ fprintf(stderr, "Could not create manager!\n");
+ exit(1);
+ }
+
+ gdk_window_add_filter(NULL, manager_event_filter, NULL);
+
+ setup_font();
+ gtk_main();
+
+ xsettings_manager_destroy(manager);
+ g_object_unref(client);
+
+ return 0;
+}
diff --git a/src/xsettings-common.c b/src/xsettings-common.c
new file mode 100644
index 0000000..3d74440
--- /dev/null
+++ b/src/xsettings-common.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#include "string.h"
+#include "stdlib.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xmd.h> /* For CARD32 */
+
+#include "xsettings-common.h"
+
+XSettingsSetting *
+xsettings_setting_copy (XSettingsSetting *setting)
+{
+ XSettingsSetting *result;
+ size_t str_len;
+
+ result = malloc (sizeof *result);
+ if (!result)
+ return NULL;
+
+ str_len = strlen (setting->name);
+ result->name = malloc (str_len + 1);
+ if (!result->name)
+ goto err;
+
+ memcpy (result->name, setting->name, str_len + 1);
+
+ result->type = setting->type;
+
+ switch (setting->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ result->data.v_int = setting->data.v_int;
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ result->data.v_color = setting->data.v_color;
+ break;
+ case XSETTINGS_TYPE_STRING:
+ str_len = strlen (setting->data.v_string);
+ result->data.v_string = malloc (str_len + 1);
+ if (!result->data.v_string)
+ goto err;
+
+ memcpy (result->data.v_string, setting->data.v_string, str_len + 1);
+ break;
+ }
+
+ result->last_change_serial = setting->last_change_serial;
+
+ return result;
+
+ err:
+ if (result->name)
+ free (result->name);
+ free (result);
+
+ return NULL;
+}
+
+XSettingsList *
+xsettings_list_copy (XSettingsList *list)
+{
+ XSettingsList *new = NULL;
+ XSettingsList *old_iter = list;
+ XSettingsList *new_iter = NULL;
+
+ while (old_iter)
+ {
+ XSettingsList *new_node;
+
+ new_node = malloc (sizeof *new_node);
+ if (!new_node)
+ goto error;
+
+ new_node->setting = xsettings_setting_copy (old_iter->setting);
+ if (!new_node->setting)
+ {
+ free (new_node);
+ goto error;
+ }
+
+ if (new_iter)
+ new_iter->next = new_node;
+ else
+ new = new_node;
+
+ new_iter = new_node;
+
+ old_iter = old_iter->next;
+ }
+
+ return new;
+
+ error:
+ xsettings_list_free (new);
+ return NULL;
+}
+
+int
+xsettings_setting_equal (XSettingsSetting *setting_a,
+ XSettingsSetting *setting_b)
+{
+ if (setting_a->type != setting_b->type)
+ return 0;
+
+ if (strcmp (setting_a->name, setting_b->name) != 0)
+ return 0;
+
+ switch (setting_a->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ return setting_a->data.v_int == setting_b->data.v_int;
+ case XSETTINGS_TYPE_COLOR:
+ return (setting_a->data.v_color.red == setting_b->data.v_color.red &&
+ setting_a->data.v_color.green == setting_b->data.v_color.green &&
+ setting_a->data.v_color.blue == setting_b->data.v_color.blue &&
+ setting_a->data.v_color.alpha == setting_b->data.v_color.alpha);
+ case XSETTINGS_TYPE_STRING:
+ return strcmp (setting_a->data.v_string, setting_b->data.v_string) == 0;
+ }
+
+ return 0;
+}
+
+void
+xsettings_setting_free (XSettingsSetting *setting)
+{
+ if (setting->type == XSETTINGS_TYPE_STRING)
+ free (setting->data.v_string);
+
+ if (setting->name)
+ free (setting->name);
+
+ free (setting);
+}
+
+void
+xsettings_list_free (XSettingsList *list)
+{
+ while (list)
+ {
+ XSettingsList *next = list->next;
+
+ xsettings_setting_free (list->setting);
+ free (list);
+
+ list = next;
+ }
+}
+
+XSettingsResult
+xsettings_list_insert (XSettingsList **list,
+ XSettingsSetting *setting)
+{
+ XSettingsList *node;
+ XSettingsList *iter;
+ XSettingsList *last = NULL;
+
+ node = malloc (sizeof *node);
+ if (!node)
+ return XSETTINGS_NO_MEM;
+ node->setting = setting;
+
+ iter = *list;
+ while (iter)
+ {
+ int cmp = strcmp (setting->name, iter->setting->name);
+
+ if (cmp < 0)
+ break;
+ else if (cmp == 0)
+ {
+ free (node);
+ return XSETTINGS_DUPLICATE_ENTRY;
+ }
+
+ last = iter;
+ iter = iter->next;
+ }
+
+ if (last)
+ last->next = node;
+ else
+ *list = node;
+
+ node->next = iter;
+
+ return XSETTINGS_SUCCESS;
+}
+
+XSettingsResult
+xsettings_list_delete (XSettingsList **list,
+ const char *name)
+{
+ XSettingsList *iter;
+ XSettingsList *last = NULL;
+
+ iter = *list;
+ while (iter)
+ {
+ if (strcmp (name, iter->setting->name) == 0)
+ {
+ if (last)
+ last->next = iter->next;
+ else
+ *list = iter->next;
+
+ xsettings_setting_free (iter->setting);
+ free (iter);
+
+ return XSETTINGS_SUCCESS;
+ }
+
+ last = iter;
+ iter = iter->next;
+ }
+
+ return XSETTINGS_FAILED;
+}
+
+XSettingsSetting *
+xsettings_list_lookup (XSettingsList *list,
+ const char *name)
+{
+ XSettingsList *iter;
+
+ iter = list;
+ while (iter)
+ {
+ if (strcmp (name, iter->setting->name) == 0)
+ return iter->setting;
+
+ iter = iter->next;
+ }
+
+ return NULL;
+}
+
+char
+xsettings_byte_order (void)
+{
+ CARD32 myint = 0x01020304;
+ return (*(char *)&myint == 1) ? MSBFirst : LSBFirst;
+}
diff --git a/src/xsettings-common.h b/src/xsettings-common.h
new file mode 100644
index 0000000..e3af4a6
--- /dev/null
+++ b/src/xsettings-common.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#ifndef XSETTINGS_COMMON_H
+#define XSETTINGS_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _XSettingsBuffer XSettingsBuffer;
+typedef struct _XSettingsColor XSettingsColor;
+typedef struct _XSettingsList XSettingsList;
+typedef struct _XSettingsSetting XSettingsSetting;
+
+/* Types of settings possible. Enum values correspond to
+ * protocol values.
+ */
+typedef enum
+{
+ XSETTINGS_TYPE_INT = 0,
+ XSETTINGS_TYPE_STRING = 1,
+ XSETTINGS_TYPE_COLOR = 2
+} XSettingsType;
+
+typedef enum
+{
+ XSETTINGS_SUCCESS,
+ XSETTINGS_NO_MEM,
+ XSETTINGS_ACCESS,
+ XSETTINGS_FAILED,
+ XSETTINGS_NO_ENTRY,
+ XSETTINGS_DUPLICATE_ENTRY
+} XSettingsResult;
+
+struct _XSettingsBuffer
+{
+ char byte_order;
+ size_t len;
+ unsigned char *data;
+ unsigned char *pos;
+};
+
+struct _XSettingsColor
+{
+ unsigned short red, green, blue, alpha;
+};
+
+struct _XSettingsList
+{
+ XSettingsSetting *setting;
+ XSettingsList *next;
+};
+
+struct _XSettingsSetting
+{
+ char *name;
+ XSettingsType type;
+
+ union {
+ int v_int;
+ char *v_string;
+ XSettingsColor v_color;
+ } data;
+
+ unsigned long last_change_serial;
+};
+
+XSettingsSetting *xsettings_setting_copy (XSettingsSetting *setting);
+void xsettings_setting_free (XSettingsSetting *setting);
+int xsettings_setting_equal (XSettingsSetting *setting_a,
+ XSettingsSetting *setting_b);
+
+void xsettings_list_free (XSettingsList *list);
+XSettingsList *xsettings_list_copy (XSettingsList *list);
+XSettingsResult xsettings_list_insert (XSettingsList **list,
+ XSettingsSetting *setting);
+XSettingsSetting *xsettings_list_lookup (XSettingsList *list,
+ const char *name);
+XSettingsResult xsettings_list_delete (XSettingsList **list,
+ const char *name);
+
+char xsettings_byte_order (void);
+
+#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1)))
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* XSETTINGS_COMMON_H */
diff --git a/src/xsettings-manager.c b/src/xsettings-manager.c
new file mode 100644
index 0000000..ced791d
--- /dev/null
+++ b/src/xsettings-manager.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xmd.h> /* For CARD16 */
+
+#include "xsettings-manager.h"
+
+struct _XSettingsManager
+{
+ Display *display;
+ int screen;
+
+ Window window;
+ Atom manager_atom;
+ Atom selection_atom;
+ Atom xsettings_atom;
+
+ XSettingsTerminateFunc terminate;
+ void *cb_data;
+
+ XSettingsList *settings;
+ unsigned long serial;
+};
+
+XSettingsList *settings;
+
+typedef struct
+{
+ Window window;
+ Atom timestamp_prop_atom;
+} TimeStampInfo;
+
+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;
+}
+
+/**
+ * get_server_time:
+ * @display: display from which to get the time
+ * @window: a #Window, used for communication with the server.
+ * The window must have PropertyChangeMask in its
+ * events mask or a hang will result.
+ *
+ * Routine to get the current X server time stamp.
+ *
+ * Return value: the time stamp.
+ **/
+static Time
+get_server_time (Display *display,
+ Window window)
+{
+ unsigned char c = 'a';
+ XEvent xevent;
+ TimeStampInfo info;
+
+ info.timestamp_prop_atom = XInternAtom (display, "_TIMESTAMP_PROP", False);
+ info.window = window;
+
+ XChangeProperty (display, window,
+ info.timestamp_prop_atom, info.timestamp_prop_atom,
+ 8, PropModeReplace, &c, 1);
+
+ XIfEvent (display, &xevent,
+ timestamp_predicate, (XPointer)&info);
+
+ return xevent.xproperty.time;
+}
+
+Bool
+xsettings_manager_check_running (Display *display,
+ int screen)
+{
+ char buffer[256];
+ Atom selection_atom;
+
+ sprintf(buffer, "_XSETTINGS_S%d", screen);
+ selection_atom = XInternAtom (display, buffer, False);
+
+ if (XGetSelectionOwner (display, selection_atom))
+ return True;
+ else
+ return False;
+}
+
+XSettingsManager *
+xsettings_manager_new (Display *display,
+ int screen,
+ XSettingsTerminateFunc terminate,
+ void *cb_data)
+{
+ XSettingsManager *manager;
+ Time timestamp;
+ XClientMessageEvent xev;
+
+ char buffer[256];
+
+ manager = malloc (sizeof *manager);
+ if (!manager)
+ return NULL;
+
+ manager->display = display;
+ manager->screen = screen;
+
+ sprintf(buffer, "_XSETTINGS_S%d", screen);
+ manager->selection_atom = XInternAtom (display, buffer, False);
+ manager->xsettings_atom = XInternAtom (display, "_XSETTINGS_SETTINGS", False);
+ manager->manager_atom = XInternAtom (display, "MANAGER", False);
+
+ manager->terminate = terminate;
+ manager->cb_data = cb_data;
+
+ manager->settings = NULL;
+ manager->serial = 0;
+
+ manager->window = XCreateSimpleWindow (display,
+ RootWindow (display, screen),
+ 0, 0, 10, 10, 0,
+ WhitePixel (display, screen),
+ WhitePixel (display, screen));
+
+ XSelectInput (display, manager->window, PropertyChangeMask);
+ timestamp = get_server_time (display, manager->window);
+
+ XSetSelectionOwner (display, manager->selection_atom,
+ manager->window, timestamp);
+
+ /* Check to see if we managed to claim the selection. If not,
+ * we treat it as if we got it then immediately lost it
+ */
+
+ if (XGetSelectionOwner (display, manager->selection_atom) ==
+ manager->window)
+ {
+ xev.type = ClientMessage;
+ xev.window = RootWindow (display, screen);
+ xev.message_type = manager->manager_atom;
+ xev.format = 32;
+ xev.data.l[0] = timestamp;
+ xev.data.l[1] = manager->selection_atom;
+ xev.data.l[2] = manager->window;
+ xev.data.l[3] = 0; /* manager specific data */
+ xev.data.l[4] = 0; /* manager specific data */
+
+ XSendEvent (display, RootWindow (display, screen),
+ False, StructureNotifyMask, (XEvent *)&xev);
+ }
+ else
+ {
+ manager->terminate (manager->cb_data);
+ }
+
+ return manager;
+}
+
+void
+xsettings_manager_destroy (XSettingsManager *manager)
+{
+ XDestroyWindow (manager->display, manager->window);
+
+ xsettings_list_free (manager->settings);
+ free (manager);
+}
+
+Window
+xsettings_manager_get_window (XSettingsManager *manager)
+{
+ return manager->window;
+}
+
+Bool
+xsettings_manager_process_event (XSettingsManager *manager,
+ XEvent *xev)
+{
+ if (xev->xany.window == manager->window &&
+ xev->xany.type == SelectionClear &&
+ xev->xselectionclear.selection == manager->selection_atom)
+ {
+ manager->terminate (manager->cb_data);
+ return True;
+ }
+
+ return False;
+}
+
+XSettingsResult
+xsettings_manager_set_setting (XSettingsManager *manager,
+ XSettingsSetting *setting)
+{
+ XSettingsSetting *old_setting = xsettings_list_lookup (settings, setting->name);
+ XSettingsSetting *new_setting;
+ XSettingsResult result;
+
+ if (old_setting)
+ {
+ if (xsettings_setting_equal (old_setting, setting))
+ return XSETTINGS_SUCCESS;
+
+ xsettings_list_delete (&settings, setting->name);
+ }
+
+ new_setting = xsettings_setting_copy (setting);
+ if (!new_setting)
+ return XSETTINGS_NO_MEM;
+
+ new_setting->last_change_serial = manager->serial;
+
+ result = xsettings_list_insert (&settings, new_setting);
+
+ if (result != XSETTINGS_SUCCESS)
+ xsettings_setting_free (new_setting);
+
+ return result;
+}
+
+XSettingsResult
+xsettings_manager_delete_setting (XSettingsManager *manager,
+ const char *name)
+{
+ return xsettings_list_delete (&settings, name);
+}
+
+XSettingsResult
+xsettings_manager_set_int (XSettingsManager *manager,
+ const char *name,
+ int value)
+{
+ XSettingsSetting setting;
+
+ setting.name = (char *)name;
+ setting.type = XSETTINGS_TYPE_INT;
+ setting.data.v_int = value;
+
+ return xsettings_manager_set_setting (manager, &setting);
+}
+
+XSettingsResult
+xsettings_manager_set_string (XSettingsManager *manager,
+ const char *name,
+ const char *value)
+{
+ XSettingsSetting setting;
+
+ setting.name = (char *)name;
+ setting.type = XSETTINGS_TYPE_STRING;
+ setting.data.v_string = (char *)value;
+
+ return xsettings_manager_set_setting (manager, &setting);
+}
+
+XSettingsResult
+xsettings_manager_set_color (XSettingsManager *manager,
+ const char *name,
+ XSettingsColor *value)
+{
+ XSettingsSetting setting;
+
+ setting.name = (char *)name;
+ setting.type = XSETTINGS_TYPE_COLOR;
+ setting.data.v_color = *value;
+
+ return xsettings_manager_set_setting (manager, &setting);
+}
+
+size_t
+setting_length (XSettingsSetting *setting)
+{
+ size_t length = 8; /* type + pad + name-len + last-change-serial */
+ length += XSETTINGS_PAD (strlen (setting->name), 4);
+
+ switch (setting->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ length += 4;
+ break;
+ case XSETTINGS_TYPE_STRING:
+ length += 4 + XSETTINGS_PAD (strlen (setting->data.v_string), 4);
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ length += 8;
+ break;
+ }
+
+ return length;
+}
+
+void
+setting_store (XSettingsSetting *setting,
+ XSettingsBuffer *buffer)
+{
+ size_t string_len;
+ size_t length;
+
+ *(buffer->pos++) = setting->type;
+ *(buffer->pos++) = 0;
+
+ string_len = strlen (setting->name);
+ *(CARD16 *)(buffer->pos) = string_len;
+ buffer->pos += 2;
+
+ length = XSETTINGS_PAD (string_len, 4);
+ memcpy (buffer->pos, setting->name, string_len);
+ length -= string_len;
+ buffer->pos += string_len;
+
+ while (length > 0)
+ {
+ *(buffer->pos++) = 0;
+ length--;
+ }
+
+ *(CARD32 *)(buffer->pos) = setting->last_change_serial;
+ buffer->pos += 4;
+
+ switch (setting->type)
+ {
+ case XSETTINGS_TYPE_INT:
+ *(CARD32 *)(buffer->pos) = setting->data.v_int;
+ buffer->pos += 4;
+ break;
+ case XSETTINGS_TYPE_STRING:
+ string_len = strlen (setting->data.v_string);
+ *(CARD32 *)(buffer->pos) = string_len;
+ buffer->pos += 4;
+
+ length = XSETTINGS_PAD (string_len, 4);
+ memcpy (buffer->pos, setting->data.v_string, string_len);
+ length -= string_len;
+ buffer->pos += string_len;
+
+ while (length > 0)
+ {
+ *(buffer->pos++) = 0;
+ length--;
+ }
+ break;
+ case XSETTINGS_TYPE_COLOR:
+ *(CARD16 *)(buffer->pos) = setting->data.v_color.red;
+ *(CARD16 *)(buffer->pos + 2) = setting->data.v_color.green;
+ *(CARD16 *)(buffer->pos + 4) = setting->data.v_color.blue;
+ *(CARD16 *)(buffer->pos + 6) = setting->data.v_color.alpha;
+ buffer->pos += 8;
+ break;
+ }
+}
+
+XSettingsResult
+xsettings_manager_notify (XSettingsManager *manager)
+{
+ XSettingsBuffer buffer;
+ XSettingsList *iter;
+ int n_settings = 0;
+
+ buffer.len = 12; /* byte-order + pad + SERIAL + N_SETTINGS */
+
+ iter = settings;
+ while (iter)
+ {
+ buffer.len += setting_length (iter->setting);
+ n_settings++;
+ iter = iter->next;
+ }
+
+ buffer.data = buffer.pos = malloc (buffer.len);
+ if (!buffer.data)
+ return XSETTINGS_NO_MEM;
+
+ *buffer.pos = xsettings_byte_order ();
+
+ buffer.pos += 4;
+ *(CARD32 *)buffer.pos = manager->serial++;
+ buffer.pos += 4;
+ *(CARD32 *)buffer.pos = n_settings;
+ buffer.pos += 4;
+
+ iter = settings;
+ while (iter)
+ {
+ setting_store (iter->setting, &buffer);
+ iter = iter->next;
+ }
+
+ XChangeProperty (manager->display, manager->window,
+ manager->xsettings_atom, manager->xsettings_atom,
+ 8, PropModeReplace, buffer.data, buffer.len);
+
+ free (buffer.data);
+
+ return XSETTINGS_SUCCESS;
+}
+
diff --git a/src/xsettings-manager.h b/src/xsettings-manager.h
new file mode 100644
index 0000000..2439b42
--- /dev/null
+++ b/src/xsettings-manager.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2001 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Owen Taylor, Red Hat, Inc.
+ */
+#ifndef XSETTINGS_MANAGER_H
+#define XSETTINGS_MANAGER_H
+
+#include <X11/Xlib.h>
+#include "xsettings-common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _XSettingsManager XSettingsManager;
+
+typedef void (*XSettingsTerminateFunc) (void *cb_data);
+
+Bool xsettings_manager_check_running (Display *display,
+ int screen);
+
+XSettingsManager *xsettings_manager_new (Display *display,
+ int screen,
+ XSettingsTerminateFunc terminate,
+ void *cb_data);
+
+void xsettings_manager_destroy (XSettingsManager *manager);
+Window xsettings_manager_get_window (XSettingsManager *manager);
+Bool xsettings_manager_process_event (XSettingsManager *manager,
+ XEvent *xev);
+
+XSettingsResult xsettings_manager_set_setting (XSettingsManager *manager,
+ XSettingsSetting *setting);
+XSettingsResult xsettings_manager_delete_setting (XSettingsManager *manager,
+ const char *name);
+XSettingsResult xsettings_manager_set_int (XSettingsManager *manager,
+ const char *name,
+ int value);
+XSettingsResult xsettings_manager_set_string (XSettingsManager *manager,
+ const char *name,
+ const char *value);
+XSettingsResult xsettings_manager_set_color (XSettingsManager *manager,
+ const char *name,
+ XSettingsColor *value);
+XSettingsResult xsettings_manager_notify (XSettingsManager *manager);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* XSETTINGS_MANAGER_H */