diff options
author | Charles Kerr <charles.kerr@canonical.com> | 2012-04-04 15:04:54 -0500 |
---|---|---|
committer | Charles Kerr <charles.kerr@canonical.com> | 2012-04-04 15:04:54 -0500 |
commit | 832062b6c5d1339726abee1c942df89ed8370bac (patch) | |
tree | cb8ce8274bc5d74720409652635d9d9fc557e077 /libdbusmenu-glib/server.c | |
parent | fe87fe143ac15a15fbe5e035de48fd5d44801878 (diff) | |
parent | 0bb911f850ebfd0f4ad2686966933272bb9bdefd (diff) | |
download | libdbusmenu-832062b6c5d1339726abee1c942df89ed8370bac.tar.gz libdbusmenu-832062b6c5d1339726abee1c942df89ed8370bac.tar.bz2 libdbusmenu-832062b6c5d1339726abee1c942df89ed8370bac.zip |
* New upstream release.
* Reduce the number of messages hud-service sends. (LP: #957022)
* Fix valgrind tests thanks to a little help from sewardj.
* Add gcov targets to autotools build for code-coverage reporting.
Diffstat (limited to 'libdbusmenu-glib/server.c')
-rw-r--r-- | libdbusmenu-glib/server.c | 189 |
1 files changed, 174 insertions, 15 deletions
diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index 1b4ce95..091b243 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -42,7 +42,7 @@ License version 3 and version 2.1 along with this program. If not, see static void layout_update_signal (DbusmenuServer * server); -#define DBUSMENU_VERSION_NUMBER 2 +#define DBUSMENU_VERSION_NUMBER 3 #define DBUSMENU_INTERFACE "com.canonical.dbusmenu" /* Privates, I'll show you mine... */ @@ -118,7 +118,9 @@ enum { METHOD_GET_PROPERTY, METHOD_GET_PROPERTIES, METHOD_EVENT, + METHOD_EVENT_GROUP, METHOD_ABOUT_TO_SHOW, + METHOD_ABOUT_TO_SHOW_GROUP, /* Counter, do not remove! */ METHOD_COUNT }; @@ -191,9 +193,15 @@ static void bus_get_properties (DbusmenuServer * server, static void bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation); +static void bus_event_group (DbusmenuServer * server, + GVariant * params, + GDBusMethodInvocation * invocation); static void bus_about_to_show (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation); +static void bus_about_to_show_group (DbusmenuServer * server, + GVariant * params, + GDBusMethodInvocation * invocation); static void find_servers_cb (GDBusConnection * connection, const gchar * sender, const gchar * path, @@ -358,9 +366,15 @@ dbusmenu_server_class_init (DbusmenuServerClass *class) dbusmenu_method_table[METHOD_EVENT].interned_name = g_intern_static_string("Event"); dbusmenu_method_table[METHOD_EVENT].func = bus_event; + dbusmenu_method_table[METHOD_EVENT_GROUP].interned_name = g_intern_static_string("EventGroup"); + dbusmenu_method_table[METHOD_EVENT_GROUP].func = bus_event_group; + dbusmenu_method_table[METHOD_ABOUT_TO_SHOW].interned_name = g_intern_static_string("AboutToShow"); dbusmenu_method_table[METHOD_ABOUT_TO_SHOW].func = bus_about_to_show; + dbusmenu_method_table[METHOD_ABOUT_TO_SHOW_GROUP].interned_name = g_intern_static_string("AboutToShowGroup"); + dbusmenu_method_table[METHOD_ABOUT_TO_SHOW_GROUP].func = bus_about_to_show_group; + return; } @@ -1633,6 +1647,28 @@ event_local_handler (gpointer user_data) return FALSE; } +/* The core menu finding and doing the work part of the two + event functions */ +static gboolean +bus_event_core (DbusmenuServer * server, gint32 id, gchar * event_type, GVariant * data, guint32 timestamp) +{ + DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id); + + if (mi == NULL) { + return FALSE; + } + + idle_event_t * event_data = g_new0(idle_event_t, 1); + event_data->mi = g_object_ref(mi); + event_data->eventid = g_strdup(event_type); + event_data->timestamp = timestamp; + event_data->variant = g_variant_ref(data); + + g_timeout_add(0, event_local_handler, event_data); + + return TRUE; +} + /* Handles the events coming off of DBus */ static void bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation) @@ -1654,34 +1690,94 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i g_variant_get(params, "(isvu)", &id, &etype, &data, &ts); - DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id); - - if (mi == NULL) { + if (!bus_event_core(server, id, etype, data, ts)) { g_dbus_method_invocation_return_error(invocation, error_quark(), INVALID_MENUITEM_ID, "The ID supplied %d does not refer to a menu item we have", id); - g_free(etype); - g_variant_unref(data); - } else { - idle_event_t * event_data = g_new0(idle_event_t, 1); - event_data->mi = g_object_ref(mi); - event_data->eventid = etype; /* give away our allocation */ - event_data->timestamp = ts; - event_data->variant = data; /* give away our reference */ + if (~g_dbus_message_get_flags (g_dbus_method_invocation_get_message (invocation)) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) { + g_dbus_method_invocation_return_value(invocation, NULL); + } + } - g_timeout_add(0, event_local_handler, event_data); + g_free(etype); + g_variant_unref(data); + + return; +} + +/* Respond to the event group method that will send events to a + variety of menuitems */ +static void +bus_event_group (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation) +{ + DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server); + + if (priv->root == NULL) { + g_dbus_method_invocation_return_error(invocation, + error_quark(), + NO_VALID_LAYOUT, + "There currently isn't a layout in this server"); + return; + } + + GVariant * events = g_variant_get_child_value(params, 0); + gint32 id; + gchar *etype; + GVariant *data; + guint32 ts; + GVariantIter iter; + GVariantBuilder builder; + + g_variant_iter_init(&iter, events); + g_variant_builder_init(&builder, G_VARIANT_TYPE("ai")); + gboolean gotone = FALSE; + + while (g_variant_iter_loop(&iter, "(isvu)", &id, &etype, &data, &ts)) { + if (bus_event_core(server, id, etype, data, ts)) { + gotone = TRUE; + } else { + g_variant_builder_add_value(&builder, g_variant_new_int32(id)); + } + } + GVariant * errors = g_variant_builder_end(&builder); + g_variant_ref_sink(errors); + + if (gotone) { if (~g_dbus_message_get_flags (g_dbus_method_invocation_get_message (invocation)) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) { - g_dbus_method_invocation_return_value(invocation, NULL); + g_dbus_method_invocation_return_value(invocation, g_variant_new_tuple(&errors, 1)); } + } else { + gchar * ids = g_variant_print(errors, FALSE); + g_dbus_method_invocation_return_error(invocation, + error_quark(), + INVALID_MENUITEM_ID, + "The IDs supplied '%s' do not refer to any menu items we have", + ids); + g_free(ids); } + g_variant_unref(errors); + g_variant_unref(events); + return; } +/* Does the about-to-show in an idle loop so we don't block things */ +/* NOTE: this only works so easily as we don't return the value, if we + were to do that it would get more complex. */ +static gboolean +bus_about_to_show_idle (gpointer user_data) +{ + DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(user_data); + dbusmenu_menuitem_send_about_to_show(mi, NULL, NULL); + g_object_unref(mi); + return FALSE; +} + /* Recieve the About To Show function. Pass it to our menu item. */ static void bus_about_to_show (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation) @@ -1709,7 +1805,7 @@ bus_about_to_show (DbusmenuServer * server, GVariant * params, GDBusMethodInvoca return; } - dbusmenu_menuitem_send_about_to_show(mi, NULL, NULL); + g_timeout_add(0, bus_about_to_show_idle, g_object_ref(mi)); /* GTK+ does not support about-to-show concept for now */ g_dbus_method_invocation_return_value(invocation, @@ -1717,6 +1813,69 @@ bus_about_to_show (DbusmenuServer * server, GVariant * params, GDBusMethodInvoca return; } +/* Handle the about to show on a set of menus and tell all of them that + we love them */ +static void +bus_about_to_show_group (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation) +{ + DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server); + + if (priv->root == NULL) { + g_dbus_method_invocation_return_error(invocation, + error_quark(), + NO_VALID_LAYOUT, + "There currently isn't a layout in this server"); + return; + } + + gint32 id; + GVariantIter iter; + GVariantBuilder builder; + + g_variant_iter_init(&iter, params); + g_variant_builder_init(&builder, G_VARIANT_TYPE("ai")); + gboolean gotone = FALSE; + + while (g_variant_iter_loop(&iter, "(i)", &id)) { + DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id); + if (mi != NULL) { + g_timeout_add(0, bus_about_to_show_idle, g_object_ref(mi)); + gotone = TRUE; + } else { + g_variant_builder_add_value(&builder, g_variant_new_int32(id)); + } + } + + GVariant * errors = g_variant_builder_end(&builder); + g_variant_ref_sink(errors); + + if (gotone) { + if (~g_dbus_message_get_flags (g_dbus_method_invocation_get_message (invocation)) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) { + GVariantBuilder tuple; + g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE); + + /* Updates needed */ + g_variant_builder_add_value(&tuple, g_variant_new_array(G_VARIANT_TYPE_INT32, NULL, 0)); + /* Errors */ + g_variant_builder_add_value(&tuple, errors); + + g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&tuple)); + } + } else { + gchar * ids = g_variant_print(errors, FALSE); + g_dbus_method_invocation_return_error(invocation, + error_quark(), + INVALID_MENUITEM_ID, + "The IDs supplied '%s' do not refer to any menu items we have", + ids); + g_free(ids); + } + + g_variant_unref(errors); + + return; +} + /* Public Interface */ /** dbusmenu_server_new: |