aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-glib/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdbusmenu-glib/server.c')
-rw-r--r--libdbusmenu-glib/server.c332
1 files changed, 332 insertions, 0 deletions
diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c
new file mode 100644
index 0000000..3db6db0
--- /dev/null
+++ b/libdbusmenu-glib/server.c
@@ -0,0 +1,332 @@
+/*
+A library to communicate a menu object set accross DBus and
+track updates and maintain consistency.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "server.h"
+#include "server-marshal.h"
+
+/* DBus Prototypes */
+static gboolean _dbusmenu_server_get_property (void);
+static gboolean _dbusmenu_server_get_properties (void);
+static gboolean _dbusmenu_server_call (void);
+static gboolean _dbusmenu_server_list_properties (void);
+
+#include "dbusmenu-server.h"
+
+/* Privates, I'll show you mine... */
+typedef struct _DbusmenuServerPrivate DbusmenuServerPrivate;
+
+struct _DbusmenuServerPrivate
+{
+ DbusmenuMenuitem * root;
+ gchar * dbusobject;
+};
+
+#define DBUSMENU_SERVER_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_TYPE_SERVER, DbusmenuServerPrivate))
+
+/* Signals */
+enum {
+ ID_PROP_UPDATE,
+ ID_UPDATE,
+ LAYOUT_UPDATE,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* Properties */
+enum {
+ PROP_0,
+ PROP_DBUS_OBJECT,
+ PROP_ROOT_NODE,
+ PROP_LAYOUT
+};
+
+/* Prototype */
+static void dbusmenu_server_class_init (DbusmenuServerClass *class);
+static void dbusmenu_server_init (DbusmenuServer *self);
+static void dbusmenu_server_dispose (GObject *object);
+static void dbusmenu_server_finalize (GObject *object);
+static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec);
+static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
+
+G_DEFINE_TYPE (DbusmenuServer, dbusmenu_server, G_TYPE_OBJECT);
+
+static void
+dbusmenu_server_class_init (DbusmenuServerClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ g_type_class_add_private (class, sizeof (DbusmenuServerPrivate));
+
+ object_class->dispose = dbusmenu_server_dispose;
+ object_class->finalize = dbusmenu_server_finalize;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ signals[ID_PROP_UPDATE] = g_signal_new(DBUSMENU_SERVER_SIGNAL_ID_PROP_UPDATE,
+ G_TYPE_FROM_CLASS(class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(DbusmenuServerClass, id_prop_update),
+ NULL, NULL,
+ _dbusmenu_server_marshal_VOID__UINT_STRING_STRING,
+ G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
+ signals[ID_UPDATE] = g_signal_new(DBUSMENU_SERVER_SIGNAL_ID_UPDATE,
+ G_TYPE_FROM_CLASS(class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(DbusmenuServerClass, id_update),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE, 1, G_TYPE_UINT);
+ signals[LAYOUT_UPDATE] = g_signal_new(DBUSMENU_SERVER_SIGNAL_LAYOUT_UPDATE,
+ G_TYPE_FROM_CLASS(class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(DbusmenuServerClass, layout_update),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+
+ g_object_class_install_property (object_class, PROP_DBUS_OBJECT,
+ g_param_spec_string(DBUSMENU_SERVER_PROP_DBUS_OBJECT, "DBus object path",
+ "The object that represents this set of menus on DBus",
+ "/org/freedesktop/dbusmenu",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_ROOT_NODE,
+ g_param_spec_object(DBUSMENU_SERVER_PROP_ROOT_NODE, "Root menu node",
+ "The base object of the menus that are served",
+ DBUSMENU_TYPE_MENUITEM,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_LAYOUT,
+ g_param_spec_string(DBUSMENU_SERVER_PROP_LAYOUT, "XML Layout of the menus",
+ "A simple XML string that describes the layout of the menus",
+ "<menu />",
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ dbus_g_object_type_install_info(DBUSMENU_TYPE_SERVER, &dbus_glib__dbusmenu_server_object_info);
+
+ return;
+}
+
+static void
+dbusmenu_server_init (DbusmenuServer *self)
+{
+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(self);
+
+ priv->root = NULL;
+ priv->dbusobject = NULL;
+
+ return;
+}
+
+static void
+dbusmenu_server_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (dbusmenu_server_parent_class)->dispose (object);
+ return;
+}
+
+static void
+dbusmenu_server_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (dbusmenu_server_parent_class)->finalize (object);
+ return;
+}
+
+static void
+set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
+{
+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(obj);
+
+ switch (id) {
+ case PROP_DBUS_OBJECT:
+ g_return_if_fail(priv->dbusobject == NULL);
+ priv->dbusobject = g_value_dup_string(value);
+ DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+ dbus_g_connection_register_g_object(connection,
+ priv->dbusobject,
+ obj);
+ break;
+ case PROP_ROOT_NODE:
+ if (priv->root != NULL) {
+ g_object_unref(G_OBJECT(priv->root));
+ priv->root = NULL;
+ }
+ priv->root = DBUSMENU_MENUITEM(g_value_get_object(value));
+ if (priv->root != NULL) {
+ g_object_ref(G_OBJECT(priv->root));
+ } else {
+ g_debug("Setting root node to NULL");
+ }
+ g_signal_emit(obj, signals[LAYOUT_UPDATE], 0, TRUE);
+ break;
+ case PROP_LAYOUT:
+ /* Can't set this, fall through to error */
+ g_warning("Can not set property: layout");
+ default:
+ g_return_if_reached();
+ break;
+ }
+
+ return;
+}
+
+static void
+xmlarray_foreach_free (gpointer arrayentry, gpointer userdata)
+{
+ if (arrayentry != NULL) {
+ /* g_debug("Freeing pointer: %s", (gchar *)arrayentry); */
+ g_free(arrayentry);
+ }
+
+ return;
+}
+
+static void
+get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
+{
+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(obj);
+
+ switch (id) {
+ case PROP_DBUS_OBJECT:
+ g_value_set_string(value, priv->dbusobject);
+ break;
+ case PROP_ROOT_NODE:
+ g_value_set_object(value, priv->root);
+ break;
+ case PROP_LAYOUT: {
+ GPtrArray * xmlarray = g_ptr_array_new();
+ if (priv->root == NULL) {
+ g_debug("Getting layout without root node!");
+ g_ptr_array_add(xmlarray, g_strdup("<menu />"));
+ } else {
+ dbusmenu_menuitem_buildxml(priv->root, xmlarray);
+ }
+ g_ptr_array_add(xmlarray, NULL);
+
+ /* build string */
+ gchar * finalstring = g_strjoinv("", (gchar **)xmlarray->pdata);
+ g_value_take_string(value, finalstring);
+ g_debug("Final string: %s", finalstring);
+
+ g_ptr_array_foreach(xmlarray, xmlarray_foreach_free, NULL);
+ g_ptr_array_free(xmlarray, TRUE);
+ break;
+ }
+ default:
+ g_return_if_reached();
+ break;
+ }
+
+ return;
+}
+
+/* DBus interface */
+static gboolean
+_dbusmenu_server_get_property (void)
+{
+
+ return TRUE;
+}
+
+static gboolean
+_dbusmenu_server_get_properties (void)
+{
+
+ return TRUE;
+}
+
+static gboolean
+_dbusmenu_server_call (void)
+{
+
+ return TRUE;
+}
+
+static gboolean
+_dbusmenu_server_list_properties (void)
+{
+
+ return TRUE;
+}
+
+/* Public Interface */
+/**
+ dbusmenu_server_new:
+ @object: The object name to show for this menu structure
+ on DBus. May be NULL.
+
+ Creates a new #DbusmenuServer object with a specific object
+ path on DBus. If @object is set to NULL the default object
+ name of "/org/freedesktop/dbusmenu" will be used.
+
+ Return value: A brand new #DbusmenuServer
+*/
+DbusmenuServer *
+dbusmenu_server_new (const gchar * object)
+{
+ if (object == NULL) {
+ object = "/org/freedesktop/dbusmenu";
+ }
+
+ DbusmenuServer * self = g_object_new(DBUSMENU_TYPE_SERVER,
+ DBUSMENU_SERVER_PROP_DBUS_OBJECT, object,
+ NULL);
+
+ return self;
+}
+
+/**
+ dbusmenu_server_set_root:
+ @self: The #DbusmenuServer object to set the root on
+ @root: The new root #DbusmenuMenuitem tree
+
+ This function contains all of the #GValue wrapping
+ required to set the property #DbusmenuServer:root-node
+ on the server @self.
+*/
+void
+dbusmenu_server_set_root (DbusmenuServer * self, DbusmenuMenuitem * root)
+{
+ g_return_if_fail(DBUSMENU_IS_SERVER(self));
+ g_return_if_fail(DBUSMENU_IS_MENUITEM(root));
+
+ g_debug("Setting root object: 0x%X", (unsigned int)root);
+ GValue rootvalue = {0};
+ g_value_init(&rootvalue, G_TYPE_OBJECT);
+ g_value_set_object(&rootvalue, root);
+ g_object_set_property(G_OBJECT(self), DBUSMENU_SERVER_PROP_ROOT_NODE, &rootvalue);
+ return;
+}
+
+
+