diff options
Diffstat (limited to 'libdbusmenu-glib')
-rw-r--r-- | libdbusmenu-glib/Makefile.am | 3 | ||||
-rw-r--r-- | libdbusmenu-glib/Makefile.in | 10 | ||||
-rw-r--r-- | libdbusmenu-glib/client.c | 83 | ||||
-rw-r--r-- | libdbusmenu-glib/client.h | 29 | ||||
-rw-r--r-- | libdbusmenu-glib/dbusmenu-glib.h | 37 | ||||
-rw-r--r-- | libdbusmenu-glib/menuitem.c | 10 | ||||
-rw-r--r-- | libdbusmenu-glib/server.c | 11 |
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); |