aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-glib
diff options
context:
space:
mode:
Diffstat (limited to 'libdbusmenu-glib')
-rw-r--r--libdbusmenu-glib/Makefile.am3
-rw-r--r--libdbusmenu-glib/Makefile.in10
-rw-r--r--libdbusmenu-glib/client.c83
-rw-r--r--libdbusmenu-glib/client.h29
-rw-r--r--libdbusmenu-glib/dbusmenu-glib.h37
-rw-r--r--libdbusmenu-glib/menuitem.c10
-rw-r--r--libdbusmenu-glib/server.c11
7 files changed, 161 insertions, 22 deletions
diff --git a/libdbusmenu-glib/Makefile.am b/libdbusmenu-glib/Makefile.am
index 8ab36f7..a139f7c 100644
--- a/libdbusmenu-glib/Makefile.am
+++ b/libdbusmenu-glib/Makefile.am
@@ -15,6 +15,7 @@ lib_LTLIBRARIES = \
libdbusmenu_glibincludedir=$(includedir)/libdbusmenu-0.4/libdbusmenu-glib/
libdbusmenu_glibinclude_HEADERS = \
+ dbusmenu-glib.h \
menuitem.h \
menuitem-proxy.h \
server.h \
@@ -140,7 +141,7 @@ introspection_sources = $(libdbusmenu_glibinclude_HEADERS)
Dbusmenu_Glib-0.4.gir: libdbusmenu-glib.la
Dbusmenu_Glib_0_4_gir_INCLUDES = \
GObject-2.0
-Dbusmenu_Glib_0_4_gir_CFLAGS = $(DBUSMENUGLIB_CFLAGS)
+Dbusmenu_Glib_0_4_gir_CFLAGS = $(DBUSMENUGLIB_CFLAGS) -I$(top_srcdir)
Dbusmenu_Glib_0_4_gir_LIBS = libdbusmenu-glib.la
Dbusmenu_Glib_0_4_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources))
Dbusmenu_Glib_0_4_gir_NAMESPACE = Dbusmenu
diff --git a/libdbusmenu-glib/Makefile.in b/libdbusmenu-glib/Makefile.in
index 3291146..9cfe106 100644
--- a/libdbusmenu-glib/Makefile.in
+++ b/libdbusmenu-glib/Makefile.in
@@ -43,12 +43,7 @@ subdir = libdbusmenu-glib
DIST_COMMON = $(libdbusmenu_glibinclude_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/dbusmenu-glib-0.4.pc.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gnome-doc-utils.m4 \
- $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
- $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/libtool.m4 \
- $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
- $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -316,6 +311,7 @@ lib_LTLIBRARIES = \
libdbusmenu_glibincludedir = $(includedir)/libdbusmenu-0.4/libdbusmenu-glib/
libdbusmenu_glibinclude_HEADERS = \
+ dbusmenu-glib.h \
menuitem.h \
menuitem-proxy.h \
server.h \
@@ -383,7 +379,7 @@ INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir)
@HAVE_INTROSPECTION_TRUE@Dbusmenu_Glib_0_4_gir_INCLUDES = \
@HAVE_INTROSPECTION_TRUE@ GObject-2.0
-@HAVE_INTROSPECTION_TRUE@Dbusmenu_Glib_0_4_gir_CFLAGS = $(DBUSMENUGLIB_CFLAGS)
+@HAVE_INTROSPECTION_TRUE@Dbusmenu_Glib_0_4_gir_CFLAGS = $(DBUSMENUGLIB_CFLAGS) -I$(top_srcdir)
@HAVE_INTROSPECTION_TRUE@Dbusmenu_Glib_0_4_gir_LIBS = libdbusmenu-glib.la
@HAVE_INTROSPECTION_TRUE@Dbusmenu_Glib_0_4_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources))
@HAVE_INTROSPECTION_TRUE@Dbusmenu_Glib_0_4_gir_NAMESPACE = Dbusmenu
diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c
index 29ed4a0..b196c9f 100644
--- a/libdbusmenu-glib/client.c
+++ b/libdbusmenu-glib/client.c
@@ -120,6 +120,15 @@ struct _event_data_t {
guint timestamp;
};
+typedef struct _type_handler_t type_handler_t;
+struct _type_handler_t {
+ DbusmenuClient * client;
+ DbusmenuClientTypeHandler cb;
+ DbusmenuClientTypeDestroyHandler destroy_cb;
+ gpointer user_data;
+ gchar * type;
+};
+
#define DBUSMENU_CLIENT_GET_PRIVATE(o) (DBUSMENU_CLIENT(o)->priv)
#define DBUSMENU_INTERFACE "com.canonical.dbusmenu"
@@ -148,6 +157,7 @@ static void item_activated (GDBusProxy * proxy, gint id, guint timestamp, Dbusme
static void menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data);
static void menuproxy_name_changed_cb (GObject * object, GParamSpec * pspec, gpointer user_data);
static void menuproxy_signal_cb (GDBusProxy * proxy, gchar * sender, gchar * signal, GVariant * params, gpointer user_data);
+static void type_handler_destroy (gpointer user_data);
/* Globals */
static GDBusNodeInfo * dbusmenu_node_info = NULL;
@@ -310,7 +320,7 @@ dbusmenu_client_init (DbusmenuClient *self)
priv->dbusproxy = 0;
priv->type_handlers = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, NULL);
+ g_free, type_handler_destroy);
priv->delayed_idle = 0;
priv->delayed_property_list = g_array_new(TRUE, FALSE, sizeof(gchar *));
@@ -517,6 +527,7 @@ get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data)
listener->callback(NULL, error, listener->user_data);
}
g_array_free(listeners, TRUE);
+ g_error_free(error);
return;
}
@@ -1140,7 +1151,6 @@ menuitem_get_properties_new_cb (GVariant * properties, GError * error, gpointer
if (error != NULL) {
g_warning("Error getting properties on a new menuitem: %s", error->message);
g_object_unref(propdata->item);
- g_free(data);
return;
}
@@ -1153,17 +1163,17 @@ menuitem_get_properties_new_cb (GVariant * properties, GError * error, gpointer
gboolean handled = FALSE;
const gchar * type;
- DbusmenuClientTypeHandler newfunc = NULL;
+ type_handler_t * th = NULL;
type = dbusmenu_menuitem_property_get(propdata->item, DBUSMENU_MENUITEM_PROP_TYPE);
if (type != NULL) {
- newfunc = g_hash_table_lookup(priv->type_handlers, type);
+ th = (type_handler_t *)g_hash_table_lookup(priv->type_handlers, type);
} else {
- newfunc = g_hash_table_lookup(priv->type_handlers, DBUSMENU_CLIENT_TYPES_DEFAULT);
+ th = (type_handler_t *)g_hash_table_lookup(priv->type_handlers, DBUSMENU_CLIENT_TYPES_DEFAULT);
}
- if (newfunc != NULL) {
- handled = newfunc(propdata->item, propdata->parent, propdata->client);
+ if (th != NULL && th->cb != NULL) {
+ handled = th->cb(propdata->item, propdata->parent, propdata->client, th->user_data);
}
#ifdef MASSIVEDEBUGGING
@@ -1277,6 +1287,8 @@ about_to_show_cb (GObject * proxy, GAsyncResult * res, gpointer userdata)
g_warning("Unable to send about_to_show: %s", error->message);
/* Note: we're just ensuring only the callback gets called */
need_update = FALSE;
+ g_error_free(error);
+ error = NULL;
} else {
g_variant_get(params, "(b)", &need_update);
g_variant_unref(params);
@@ -1441,7 +1453,7 @@ parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * it
/* We've got everything built up at this node and reconcilled */
/* Flush the properties requests if this is the first level */
- if (dbusmenu_menuitem_get_id(parent) == 0) {
+ if (parent != NULL && dbusmenu_menuitem_get_id(parent) == 0) {
get_properties_flush(client);
}
@@ -1553,6 +1565,7 @@ update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data)
if (error != NULL) {
g_warning("Getting layout failed: %s", error->message);
+ g_error_free(error);
return;
}
@@ -1676,6 +1689,19 @@ dbusmenu_client_get_root (DbusmenuClient * client)
return priv->root;
}
+/* Remove the type handler when we're all done with it */
+static void
+type_handler_destroy (gpointer user_data)
+{
+ type_handler_t * th = (type_handler_t *)user_data;
+ if (th->destroy_cb != NULL) {
+ th->destroy_cb(th->client, th->type, th->user_data);
+ }
+ g_free(th->type);
+ g_free(th);
+ return;
+}
+
/**
dbusmenu_client_add_type_handler:
@client: Client where we're getting types coming in
@@ -1700,6 +1726,37 @@ dbusmenu_client_get_root (DbusmenuClient * client)
gboolean
dbusmenu_client_add_type_handler (DbusmenuClient * client, const gchar * type, DbusmenuClientTypeHandler newfunc)
{
+ return dbusmenu_client_add_type_handler_full(client, type, newfunc, NULL, NULL);
+}
+
+/**
+ dbusmenu_client_add_type_handler_full:
+ @client: Client where we're getting types coming in
+ @type: A text string that will be matched with the 'type'
+ property on incoming menu items
+ @newfunc: The function that will be executed with those new
+ items when they come in.
+ @user_data: Data passed to @newfunc when it is called
+ @destroy_func: A function that is called when the type handler is
+ removed (usually on client destruction) which will free
+ the resources in @user_data.
+
+ This function connects into the type handling of the #DbusmenuClient.
+ Every new menuitem that comes in immediately gets asked for it's
+ properties. When we get those properties we check the 'type'
+ property and look to see if it matches a handler that is known
+ by the client. If so, the @newfunc function is executed on that
+ #DbusmenuMenuitem. If not, then the DbusmenuClient::new-menuitem
+ signal is sent.
+
+ In the future the known types will be sent to the server so that it
+ can make choices about the menu item types availble.
+
+ Return value: If registering the new type was successful.
+*/
+gboolean
+dbusmenu_client_add_type_handler_full (DbusmenuClient * client, const gchar * type, DbusmenuClientTypeHandler newfunc, gpointer user_data, DbusmenuClientTypeDestroyHandler destroy_func)
+{
g_return_val_if_fail(DBUSMENU_IS_CLIENT(client), FALSE);
g_return_val_if_fail(type != NULL, FALSE);
@@ -1720,6 +1777,14 @@ dbusmenu_client_add_type_handler (DbusmenuClient * client, const gchar * type, D
return FALSE;
}
- g_hash_table_insert(priv->type_handlers, g_strdup(type), newfunc);
+ type_handler_t * th = g_new0(type_handler_t, 1);
+ th->client = client;
+ th->cb = newfunc;
+ th->destroy_cb = destroy_func;
+ th->user_data = user_data;
+ th->type = g_strdup(type);
+
+ g_hash_table_insert(priv->type_handlers, g_strdup(type), th);
return TRUE;
}
+
diff --git a/libdbusmenu-glib/client.h b/libdbusmenu-glib/client.h
index 1ae89fa..6d78edf 100644
--- a/libdbusmenu-glib/client.h
+++ b/libdbusmenu-glib/client.h
@@ -110,7 +110,29 @@ struct _DbusmenuClient {
DbusmenuClientPrivate * priv;
};
-typedef gboolean (*DbusmenuClientTypeHandler) (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
+/**
+ DbusmenuClientTypeHandler:
+ @newitem: The #DbusmenuMenuitem that was created
+ @parent: The parent of @newitem or #NULL if none
+ @client: A pointer to the #DbusmenuClient
+ @user_data: The data you gave us
+
+ The type handler is called when a dbusmenu item is created
+ with a matching type as setup in #dbusmenu_client_add_type_handler
+*/
+typedef gboolean (*DbusmenuClientTypeHandler) (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
+
+/**
+ DbusmenuClientTypeDestroyHandler:
+ @client: A pointer to the #DbusmenuClient
+ @type: The type that this handler was registered with
+ @user_data: The data you gave us
+
+ This handler is called when the type becomes unregistered by the
+ client. This is usally caused by the #DbusmenuClient being destroyed
+ and should free memory or unref objects in @user_data.
+*/
+typedef void (*DbusmenuClientTypeDestroyHandler) (DbusmenuClient * client, const gchar * type, gpointer user_data);
GType dbusmenu_client_get_type (void);
DbusmenuClient * dbusmenu_client_new (const gchar * name,
@@ -119,6 +141,11 @@ DbusmenuMenuitem * dbusmenu_client_get_root (DbusmenuClient * client)
gboolean dbusmenu_client_add_type_handler (DbusmenuClient * client,
const gchar * type,
DbusmenuClientTypeHandler newfunc);
+gboolean dbusmenu_client_add_type_handler_full (DbusmenuClient * client,
+ const gchar * type,
+ DbusmenuClientTypeHandler newfunc,
+ gpointer user_data,
+ DbusmenuClientTypeDestroyHandler destory_func);
void dbusmenu_client_send_event (DbusmenuClient * client,
gint id,
const gchar * name,
diff --git a/libdbusmenu-glib/dbusmenu-glib.h b/libdbusmenu-glib/dbusmenu-glib.h
new file mode 100644
index 0000000..9c377ca
--- /dev/null
+++ b/libdbusmenu-glib/dbusmenu-glib.h
@@ -0,0 +1,37 @@
+/*
+A library to communicate a menu object set accross DBus and
+track updates and maintain consistency.
+
+Copyright 2011 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/>
+*/
+
+#ifndef __DBUSMENU_GLIB_H__
+#define __DBUSMENU_GLIB_H__
+
+#include <libdbusmenu-glib/client.h>
+#include <libdbusmenu-glib/menuitem.h>
+#include <libdbusmenu-glib/menuitem-proxy.h>
+#include <libdbusmenu-glib/server.h>
+
+#endif /* __DBUSMENU_GLIB_H__ */
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c
index 827d6c5..b40195c 100644
--- a/libdbusmenu-glib/menuitem.c
+++ b/libdbusmenu-glib/menuitem.c
@@ -1204,11 +1204,17 @@ dbusmenu_menuitem_properties_list (DbusmenuMenuitem * mi)
return g_hash_table_get_keys(priv->properties);
}
+/* Copy the keys and make references to the variants that are
+ in the new table. They'll be free'd and unref'd when the
+ Hashtable gets destroyed. */
static void
copy_helper (gpointer in_key, gpointer in_value, gpointer in_data)
{
GHashTable * table = (GHashTable *)in_data;
- g_hash_table_insert(table, in_key, in_value);
+ gchar * key = (gchar *)in_key;
+ GVariant * value = (GVariant *)in_value;
+ g_variant_ref(value);
+ g_hash_table_insert(table, g_strdup(key), value);
return;
}
@@ -1229,7 +1235,7 @@ copy_helper (gpointer in_key, gpointer in_value, gpointer in_data)
GHashTable *
dbusmenu_menuitem_properties_copy (DbusmenuMenuitem * mi)
{
- GHashTable * ret = g_hash_table_new(g_str_hash, g_str_equal);
+ GHashTable * ret = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _g_variant_unref);
g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), ret);
diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c
index 095f333..adb9f91 100644
--- a/libdbusmenu-glib/server.c
+++ b/libdbusmenu-glib/server.c
@@ -975,11 +975,17 @@ serialize_menuitem(gpointer data, gpointer user_data)
{
DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(data);
GVariantBuilder * builder = (GVariantBuilder *)(user_data);
+ GVariantBuilder tuple;
+
+ g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE);
gint id = dbusmenu_menuitem_get_id(mi);
+ g_variant_builder_add_value(&tuple, g_variant_new_int32(id));
+
GVariant * props = dbusmenu_menuitem_properties_variant(mi);
+ g_variant_builder_add_value(&tuple, props);
- g_variant_builder_add(builder, "ia{sv}", id, props);
+ g_variant_builder_add_value(builder, g_variant_builder_end(&tuple));
return;
}
@@ -1020,7 +1026,8 @@ bus_get_children (DbusmenuServer * server, GVariant * params, GDBusMethodInvocat
g_list_foreach(children, serialize_menuitem, &builder);
- ret = g_variant_new("(a(ia{svg}))", g_variant_builder_end(&builder));
+ GVariant * end = g_variant_builder_end(&builder);
+ ret = g_variant_new_tuple(&end, 1);
} else {
GError * error = NULL;
ret = g_variant_parse(g_variant_type_new("(a(ia{sv}))"), "([(0, {})],)", NULL, NULL, &error);