From 10a0d01be7c04b0538fa183451d18950d613b563 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 08:31:59 -0500 Subject: Bumping the version of the wire protocol --- libdbusmenu-glib/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index a8e9214..d85c5fa 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... */ -- cgit v1.2.3 From 0a596687cc1ffe4beb1cbfdc8605b29245f1537c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 09:08:51 -0500 Subject: Adding two grouping functions for events and about to show --- libdbusmenu-glib/dbus-menu.xml | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/libdbusmenu-glib/dbus-menu.xml b/libdbusmenu-glib/dbus-menu.xml index 4b5a5d8..1350349 100644 --- a/libdbusmenu-glib/dbus-menu.xml +++ b/libdbusmenu-glib/dbus-menu.xml @@ -326,6 +326,20 @@ License version 3 and version 2.1 along with this program. If not, see + + + Used to pass a set of events as a single message for possibily several + different menuitems. This is done to optimize DBus traffic. + + + + An array of all the events that should be passed. This tuple should + match the parameters of the 'Event' signal. Which is roughly: + id, eventID, data and timestamp. + + + + This is called by the applet to notify the application that it is about @@ -343,6 +357,26 @@ License version 3 and version 2.1 along with this program. If not, see + + + A function to tell several menus being shown that they are about to + be shown to the user. This is likely only useful for programitc purposes + so while the return values are returned, in general, the singular function + should be used in most user interacation scenarios. + + + + The IDs of the menu items who's submenus are being shown. + + + + + The IDs of the menus that need updates. Note: if no update information + is needed the DBus message should set the no reply flag. + + + + -- cgit v1.2.3 From 52617668cec85a2864819b3f86073096a7543363 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 09:27:35 -0500 Subject: Put in functions to handle the new group functions --- libdbusmenu-glib/server.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index d85c5fa..0eff073 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -116,7 +116,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 }; @@ -189,9 +191,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, @@ -356,9 +364,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; } @@ -1634,6 +1648,15 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i 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) +{ + /* TODO: DO THIS */ + return; +} + /* Recieve the About To Show function. Pass it to our menu item. */ static void bus_about_to_show (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation) @@ -1669,6 +1692,15 @@ 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) +{ + /* TODO: DO THIS */ + return; +} + /* Public Interface */ /** dbusmenu_server_new: -- cgit v1.2.3 From bc358d3583dc68af36648d09f74d39fa1665c647 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 09:38:16 -0500 Subject: Pulling the core event handling into its own function --- libdbusmenu-glib/server.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index e67ec58..04b9b68 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -1647,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 = event_type; /* give away our allocation */ + event_data->timestamp = timestamp; + event_data->variant = data; /* give away our reference */ + + 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) @@ -1668,9 +1690,7 @@ 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, @@ -1678,16 +1698,7 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i 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 */ - - g_timeout_add(0, event_local_handler, event_data); - 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); } -- cgit v1.2.3 From c02a1c5a7461c0df16428c6f5d0880c4cc502f38 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 10:32:20 -0500 Subject: Adding a way to give a partial error of IDs not being found --- libdbusmenu-glib/dbus-menu.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libdbusmenu-glib/dbus-menu.xml b/libdbusmenu-glib/dbus-menu.xml index 1350349..de6868c 100644 --- a/libdbusmenu-glib/dbus-menu.xml +++ b/libdbusmenu-glib/dbus-menu.xml @@ -338,6 +338,12 @@ License version 3 and version 2.1 along with this program. If not, see id, eventID, data and timestamp. + + + I list of menuitem IDs that couldn't be found. If none of the ones + in the list can be found, a DBus error is returned. + + @@ -375,6 +381,12 @@ License version 3 and version 2.1 along with this program. If not, see is needed the DBus message should set the no reply flag. + + + I list of menuitem IDs that couldn't be found. If none of the ones + in the list can be found, a DBus error is returned. + + -- cgit v1.2.3 From 37c153112c49f04f44cf1781ee49d369ac3ea84c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 10:32:36 -0500 Subject: Fleshing out the event group function --- libdbusmenu-glib/server.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index 04b9b68..ab1e0bc 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -1712,7 +1712,54 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i static void bus_event_group (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation) { - /* TODO: DO THIS */ + 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; + gchar *etype; + GVariant *data; + guint32 ts; + 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, "(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, 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); + return; } -- cgit v1.2.3 From 2d42ea2907a69630d5d7d6af242914a595727b86 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 10:34:16 -0500 Subject: Make it so the memory handling of the event_core function is more predictable and correct. --- libdbusmenu-glib/server.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index ab1e0bc..39641a5 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -1660,9 +1660,9 @@ bus_event_core (DbusmenuServer * server, gint32 id, gchar * event_type, GVariant idle_event_t * event_data = g_new0(idle_event_t, 1); event_data->mi = g_object_ref(mi); - event_data->eventid = event_type; /* give away our allocation */ + event_data->eventid = g_strdup(event_type); event_data->timestamp = timestamp; - event_data->variant = data; /* give away our reference */ + event_data->variant = g_variant_ref(data); g_timeout_add(0, event_local_handler, event_data); @@ -1696,14 +1696,15 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i 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 { 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_free(etype); + g_variant_unref(data); + return; } -- cgit v1.2.3 From 89c84d51382ed5ea769d9ff40eed7062c06214fc Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 11:12:21 -0500 Subject: Fleshing out the about-to-show group handler --- libdbusmenu-glib/server.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index 39641a5..289a332 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -1804,7 +1804,61 @@ bus_about_to_show (DbusmenuServer * server, GVariant * params, GDBusMethodInvoca static void bus_about_to_show_group (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation) { - /* TODO: DO THIS */ + 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) { + dbusmenu_menuitem_send_about_to_show(mi, NULL, NULL); + 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; } -- cgit v1.2.3 From c780e1632e57e24233ee374d96b74375c881696b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 11:16:56 -0500 Subject: Move the actual about-to-show call into the idle incase we get a ton of them (I'm looking at you HUD) --- libdbusmenu-glib/server.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index 289a332..2ba45d9 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -1764,6 +1764,18 @@ bus_event_group (DbusmenuServer * server, GVariant * params, GDBusMethodInvocati 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) @@ -1791,7 +1803,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, @@ -1825,7 +1837,7 @@ bus_about_to_show_group (DbusmenuServer * server, GVariant * params, GDBusMethod while (g_variant_iter_loop(&iter, "(i)", &id)) { DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id); if (mi != NULL) { - dbusmenu_menuitem_send_about_to_show(mi, NULL, 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)); -- cgit v1.2.3 From cca3468ea7fcb8d4e96fb7af9b10ba9e23f49a25 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 11:28:34 -0500 Subject: Start by adding the data we're going to need to our private structure --- libdbusmenu-glib/client.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 7d96db3..3fb5e2c 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -100,6 +100,10 @@ struct _DbusmenuClientPrivate DbusmenuTextDirection text_direction; DbusmenuStatus status; GStrv icon_dirs; + + gboolean group_events; + gulong event_idle; + GVariantBuilder events_to_go; }; typedef struct _newItemPropData newItemPropData; @@ -380,6 +384,10 @@ dbusmenu_client_init (DbusmenuClient *self) priv->status = DBUSMENU_STATUS_NORMAL; priv->icon_dirs = NULL; + priv->group_events = FALSE; + priv->event_idle = 0; + /* Note: Not initing events_to_go */ + return; } @@ -393,6 +401,15 @@ dbusmenu_client_dispose (GObject *object) priv->delayed_idle = 0; } + if (priv->event_idle != 0) { + g_source_remove(priv->event_idle); + priv->event_idle = 0; + + GVariant * data = g_variant_builder_end(&priv->events_to_go); + g_variant_ref_sink(data); + g_variant_unref(data); + } + /* Only used for queueing up a new command, so we can just drop this array. */ if (priv->delayed_property_list != NULL) { -- cgit v1.2.3 From aa9f1edc44962334c34429d7c1fe30da79bcb557 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 12:03:34 -0500 Subject: Handle the case of sending to the idle. --- libdbusmenu-glib/client.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 3fb5e2c..5492d5b 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1538,6 +1538,15 @@ menuitem_call_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) return; } +/* Group all the events into a single Dbus message and send + that out */ +static gboolean +event_idle_cb (gpointer user_data) +{ + /* TODO: DO IT! */ + return FALSE; +} + /* Sends the event over DBus to the server on the other side of the bus. */ void @@ -1557,6 +1566,25 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name variant = g_variant_new_int32(0); } + /* We want to collect as many events as we can */ + if (priv->group_events) { + if (priv->event_idle == 0) { + priv->event_idle = g_idle_add(event_idle_cb, client); + g_variant_builder_init(&priv->events_to_go, G_VARIANT_TYPE("a(isvu)")); + } + + GVariantBuilder tuple; + g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE); + + g_variant_builder_add_value(&tuple, g_variant_new_int32(id)); + g_variant_builder_add_value(&tuple, g_variant_new_string(name)); + g_variant_builder_add_value(&tuple, variant); + g_variant_builder_add_value(&tuple, g_variant_new_uint32(timestamp)); + + g_variant_builder_add_value(&priv->events_to_go, g_variant_builder_end(&tuple)); + return; + } + /* Don't bother with the reply handling if nobody is watching... */ if (!g_signal_has_handler_pending (client, signals[EVENT_RESULT], 0, TRUE)) { g_dbus_proxy_call(priv->menuproxy, -- cgit v1.2.3 From 573a0198ca970798e4e66072dde026f801b058af Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 13:49:35 -0500 Subject: Splitting out the ending of the event_data object --- libdbusmenu-glib/client.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 5492d5b..770bb44 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1505,6 +1505,22 @@ out: return; } +/* A function to work with an event_data_t and make sure it gets + free'd and in a terminal state. */ +static void +event_data_end (event_data_t * edata, GError * error) +{ + g_signal_emit(edata->client, signals[EVENT_RESULT], 0, edata->menuitem, edata->event, edata->variant, edata->timestamp, error, TRUE); + + g_variant_unref(edata->variant); + g_free(edata->event); + g_object_unref(edata->menuitem); + g_object_unref(edata->client); + g_free(edata); + + return; +} + /* Respond to the call function to make sure that the other side got it, or print a warning. */ static void @@ -1520,13 +1536,7 @@ menuitem_call_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) g_warning("Unable to call event '%s' on menu item %d: %s", edata->event, dbusmenu_menuitem_get_id(edata->menuitem), error->message); } - g_signal_emit(edata->client, signals[EVENT_RESULT], 0, edata->menuitem, edata->event, edata->variant, edata->timestamp, error, TRUE); - - g_variant_unref(edata->variant); - g_free(edata->event); - g_object_unref(edata->menuitem); - g_object_unref(edata->client); - g_free(edata); + event_data_end(edata, error); if (G_UNLIKELY(error != NULL)) { g_error_free(error); -- cgit v1.2.3 From bd2c0ad2654ec7baf230d99870469cd99e1993b4 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 13:50:09 -0500 Subject: Switching to a linked list of event_data structures getting passed to the idle function --- libdbusmenu-glib/client.c | 60 +++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 770bb44..eb6c9fb 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -103,7 +103,7 @@ struct _DbusmenuClientPrivate gboolean group_events; gulong event_idle; - GVariantBuilder events_to_go; + GList * events_to_go; /* type: event_data_t * */ }; typedef struct _newItemPropData newItemPropData; @@ -175,6 +175,7 @@ static void menuproxy_prop_changed_cb (GDBusProxy * proxy, GVariant * properties 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); +static void event_data_end (event_data_t * eventd, GError * error); /* Globals */ static GDBusNodeInfo * dbusmenu_node_info = NULL; @@ -386,7 +387,7 @@ dbusmenu_client_init (DbusmenuClient *self) priv->group_events = FALSE; priv->event_idle = 0; - /* Note: Not initing events_to_go */ + priv->events_to_go = NULL; return; } @@ -404,10 +405,14 @@ dbusmenu_client_dispose (GObject *object) if (priv->event_idle != 0) { g_source_remove(priv->event_idle); priv->event_idle = 0; + } - GVariant * data = g_variant_builder_end(&priv->events_to_go); - g_variant_ref_sink(data); - g_variant_unref(data); + if (priv->events_to_go != NULL) { + GError * error = g_error_new_literal(error_domain(), 1, "Client disposed before event signal returned"); + g_list_foreach(priv->events_to_go, (GFunc)event_data_end, error); + g_list_free(priv->events_to_go); + priv->events_to_go = NULL; + g_error_free(error); } /* Only used for queueing up a new command, so we can @@ -1576,27 +1581,8 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name variant = g_variant_new_int32(0); } - /* We want to collect as many events as we can */ - if (priv->group_events) { - if (priv->event_idle == 0) { - priv->event_idle = g_idle_add(event_idle_cb, client); - g_variant_builder_init(&priv->events_to_go, G_VARIANT_TYPE("a(isvu)")); - } - - GVariantBuilder tuple; - g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE); - - g_variant_builder_add_value(&tuple, g_variant_new_int32(id)); - g_variant_builder_add_value(&tuple, g_variant_new_string(name)); - g_variant_builder_add_value(&tuple, variant); - g_variant_builder_add_value(&tuple, g_variant_new_uint32(timestamp)); - - g_variant_builder_add_value(&priv->events_to_go, g_variant_builder_end(&tuple)); - return; - } - /* Don't bother with the reply handling if nobody is watching... */ - if (!g_signal_has_handler_pending (client, signals[EVENT_RESULT], 0, TRUE)) { + if (!priv->group_events && !g_signal_has_handler_pending (client, signals[EVENT_RESULT], 0, TRUE)) { g_dbus_proxy_call(priv->menuproxy, "Event", g_variant_new("(isvu)", id, name, variant, timestamp), @@ -1617,14 +1603,22 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name edata->variant = variant; g_variant_ref_sink(variant); - g_dbus_proxy_call(priv->menuproxy, - "Event", - g_variant_new("(isvu)", id, name, variant, timestamp), - G_DBUS_CALL_FLAGS_NONE, - 1000, /* timeout */ - NULL, /* cancellable */ - menuitem_call_cb, - edata); + if (!priv->group_events) { + g_dbus_proxy_call(priv->menuproxy, + "Event", + g_variant_new("(isvu)", id, name, variant, timestamp), + G_DBUS_CALL_FLAGS_NONE, + 1000, /* timeout */ + NULL, /* cancellable */ + menuitem_call_cb, + edata); + } else { + priv->events_to_go = g_list_prepend(priv->events_to_go, edata); + + if (priv->event_idle == 0) { + priv->event_idle = g_idle_add(event_idle_cb, client); + } + } return; } -- cgit v1.2.3 From a798c41eccf429327ea6b06d97c9a2878d4db4fe Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 14:30:28 -0500 Subject: Flesh out the idle callback so we're not actually sending a message on DBus! --- libdbusmenu-glib/client.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index eb6c9fb..29a8565 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -124,6 +124,7 @@ struct _properties_listener_t { typedef struct _event_data_t event_data_t; struct _event_data_t { + gint id; DbusmenuClient * client; DbusmenuMenuitem * menuitem; gchar * event; @@ -1553,12 +1554,64 @@ menuitem_call_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) return; } +/* Turn an event structure into the variant builder form */ +static void +events_to_builder (gpointer data, gpointer user_data) +{ + event_data_t * edata = (event_data_t *)data; + GVariantBuilder * builder = (GVariantBuilder *)user_data; + + GVariantBuilder tuple; + g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE); + + g_variant_builder_add_value(&tuple, g_variant_new_int32(edata->id)); + g_variant_builder_add_value(&tuple, g_variant_new_string(edata->event)); + g_variant_builder_add_value(&tuple, edata->variant); + g_variant_builder_add_value(&tuple, g_variant_new_uint32(edata->timestamp)); + + g_variant_builder_add_value(builder, g_variant_builder_end(&tuple)); + return; +} + /* Group all the events into a single Dbus message and send that out */ static gboolean event_idle_cb (gpointer user_data) { - /* TODO: DO IT! */ + g_return_val_if_fail(DBUSMENU_IS_CLIENT(user_data), FALSE); + DbusmenuClient * client = DBUSMENU_CLIENT(user_data); + DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(user_data); + + /* We use prepend for speed, but now we want to have them + in the order they were called incase that matters. */ + GList * levents = g_list_reverse(priv->events_to_go); + priv->events_to_go = NULL; + + GVariantBuilder array; + g_variant_builder_init(&array, G_VARIANT_TYPE("a(isvu)")); + g_list_foreach(levents, events_to_builder, &array); + GVariant * vevents = g_variant_builder_end(&array); + + if (g_signal_has_handler_pending (client, signals[EVENT_RESULT], 0, TRUE)) { + g_dbus_proxy_call(priv->menuproxy, + "EventGroup", + g_variant_new_tuple(&vevents, 1), + G_DBUS_CALL_FLAGS_NONE, + 1000, /* timeout */ + NULL, /* cancellable */ + NULL /* TODO group callback */, levents); + } else { + g_dbus_proxy_call(priv->menuproxy, + "EventGroup", + g_variant_new_tuple(&vevents, 1), + G_DBUS_CALL_FLAGS_NONE, + 1000, /* timeout */ + NULL, /* cancellable */ + NULL, NULL); + g_list_foreach(levents, (GFunc)event_data_end, NULL); + g_list_free(levents); + } + return FALSE; } @@ -1594,6 +1647,7 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name } event_data_t * edata = g_new0(event_data_t, 1); + edata->id = id; edata->client = client; g_object_ref(client); edata->menuitem = mi; -- cgit v1.2.3 From f99993dcaa21a84d5cb7c8bf91796d73c169a58f Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 15:15:17 -0500 Subject: Setting up our callback function --- libdbusmenu-glib/client.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 29a8565..1bc60a6 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1554,6 +1554,19 @@ menuitem_call_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) return; } +/* The callback from the dbus message to pass events to the + to the server en masse */ +static void +event_group_cb (GObject * proxy, GAsyncResult * res, gpointer user_data) +{ + GList * events = (GList *)user_data; + + + g_list_foreach(events, (GFunc)event_data_end, NULL); + g_list_free(events); + return; +} + /* Turn an event structure into the variant builder form */ static void events_to_builder (gpointer data, gpointer user_data) @@ -1599,7 +1612,7 @@ event_idle_cb (gpointer user_data) G_DBUS_CALL_FLAGS_NONE, 1000, /* timeout */ NULL, /* cancellable */ - NULL /* TODO group callback */, levents); + event_group_cb, levents); } else { g_dbus_proxy_call(priv->menuproxy, "EventGroup", -- cgit v1.2.3 From c050eb6d3b6dd9e6aaa297ed5354036c9845230e Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 15:18:44 -0500 Subject: Putting a warning in dispose for something we shouldn't have to do --- libdbusmenu-glib/client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 1bc60a6..1e67a65 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -409,6 +409,7 @@ dbusmenu_client_dispose (GObject *object) } if (priv->events_to_go != NULL) { + g_warning("Getting to client dispose with events pending. This is odd. Probably there's a ref count problem somewhere, but we're going to be cool about it now and clean up. But there's probably a bug."); GError * error = g_error_new_literal(error_domain(), 1, "Client disposed before event signal returned"); g_list_foreach(priv->events_to_go, (GFunc)event_data_end, error); g_list_free(priv->events_to_go); -- cgit v1.2.3 From 6b4e901d0618b1ead4a3c6230e0bd0ff43536ed3 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 15:21:39 -0500 Subject: Make the getting of properties debug messages as they can happen in normal usage --- libdbusmenu-glib/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 1e67a65..b2ee337 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -673,7 +673,7 @@ get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data) for (i = 0; i < listeners->len; i++) { properties_listener_t * listener = &g_array_index(listeners, properties_listener_t, i); if (!listener->replied) { - g_warning("Generating properties error for: %d", listener->id); + g_debug("Generating properties error for: %d", listener->id); if (localerror == NULL) { g_set_error_literal(&localerror, error_domain(), 0, "Error getting properties for ID"); } @@ -1465,7 +1465,7 @@ menuitem_get_properties_new_cb (GVariant * properties, GError * error, gpointer newItemPropData * propdata = (newItemPropData *)data; if (error != NULL) { - g_warning("Error getting properties on a new menuitem: %s", error->message); + g_debug("Error getting properties on a new menuitem: %s", error->message); goto out; } -- cgit v1.2.3 From ea39b9a3af989d4b6913b34245c97c85b652b11b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 15:43:20 -0500 Subject: Okay, making all the callbacks real and returning appropriate errors --- libdbusmenu-glib/client.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index b2ee337..5cf9d18 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -66,6 +66,12 @@ enum { LAST_SIGNAL }; +/* Errors */ +enum { + ERROR_DISPOSAL, + ERROR_ID_NOT_FOUND +}; + typedef void (*properties_func) (GVariant * properties, GError * error, gpointer user_data); static guint signals[LAST_SIGNAL] = { 0 }; @@ -410,7 +416,7 @@ dbusmenu_client_dispose (GObject *object) if (priv->events_to_go != NULL) { g_warning("Getting to client dispose with events pending. This is odd. Probably there's a ref count problem somewhere, but we're going to be cool about it now and clean up. But there's probably a bug."); - GError * error = g_error_new_literal(error_domain(), 1, "Client disposed before event signal returned"); + GError * error = g_error_new_literal(error_domain(), ERROR_DISPOSAL, "Client disposed before event signal returned"); g_list_foreach(priv->events_to_go, (GFunc)event_data_end, error); g_list_free(priv->events_to_go); priv->events_to_go = NULL; @@ -1555,6 +1561,20 @@ menuitem_call_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) return; } +/* Looks at event_data_t structs to match an ID */ +gint +event_data_find (gconstpointer data, gconstpointer user_data) +{ + event_data_t * edata = (event_data_t *)data; + gint id = GPOINTER_TO_INT(user_data); + + if (edata->id == id) { + return 0; + } else { + return -1; + } +} + /* The callback from the dbus message to pass events to the to the server en masse */ static void @@ -1562,7 +1582,39 @@ event_group_cb (GObject * proxy, GAsyncResult * res, gpointer user_data) { GList * events = (GList *)user_data; + GError * error; + GVariant * params; + params = g_dbus_proxy_call_finish(G_DBUS_PROXY(proxy), res, &error); + + if (error != NULL) { + /* If we got an actual DBus error, we should just pass that + along and finish up */ + g_list_foreach(events, (GFunc)event_data_end, error); + g_list_free(events); + events = NULL; + return; + } + + gint id = 0; + GVariant * array = g_variant_get_child_value(params, 0); + GVariantIter iter; + g_variant_iter_init(&iter, array); + + while (g_variant_iter_loop(&iter, "i", &id)) { + GList * item = g_list_find_custom(events, GINT_TO_POINTER(id), event_data_find); + + if (item != NULL) { + GError * iderror = g_error_new(error_domain(), ERROR_ID_NOT_FOUND, "Unable to find ID: %d", id); + event_data_end((event_data_t *)item->data, iderror); + events = g_list_delete_link(events, item); + g_error_free(iderror); + } + } + + g_variant_unref(array); + g_variant_unref(params); + /* If we have any left send non-error responses */ g_list_foreach(events, (GFunc)event_data_end, NULL); g_list_free(events); return; -- cgit v1.2.3 From e1e8d32c77993e0ebddaeee4064c7b94d852246c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 16:04:30 -0500 Subject: Checking the version of the server to see if we can group the properties --- libdbusmenu-glib/client.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 5cf9d18..2d07f0c 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1147,6 +1147,25 @@ menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data) g_variant_unref(icon_dirs); } + /* Get the icon theme directories if available */ + GVariant * version = g_dbus_proxy_get_cached_property(priv->menuproxy, "Version"); + if (version != NULL) { + guint32 remote_version = 0; + + if (g_variant_is_of_type(version, G_VARIANT_TYPE_UINT32)) { + remote_version = g_variant_get_uint32(version); + } + + if (remote_version >= 3) { + priv->group_events = TRUE; + } else { + priv->group_events = FALSE; + } + + g_variant_unref(version); + version = NULL; + } + /* If we get here, we don't need the DBus proxy */ if (priv->dbusproxy != 0) { g_bus_unwatch_name(priv->dbusproxy); @@ -1226,6 +1245,19 @@ menuproxy_prop_changed_cb (GDBusProxy * proxy, GVariant * properties, GStrv inva priv->icon_dirs = g_variant_dup_strv(value, NULL); dirs_changed = TRUE; } + if (g_strcmp0(key, "Version") == 0) { + guint32 remote_version = 0; + + if (g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) { + remote_version = g_variant_get_uint32(value); + } + + if (remote_version >= 3) { + priv->group_events = TRUE; + } else { + priv->group_events = FALSE; + } + } } if (olddir != priv->text_direction) { -- cgit v1.2.3 From 5cefd27bef67d8408c403edce24d4ab3bbc8fc67 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 16:05:20 -0500 Subject: If we're going to unref we should set to NULL to catch potential errors --- libdbusmenu-glib/client.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 2d07f0c..98329a1 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1116,6 +1116,7 @@ menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data) g_object_notify(G_OBJECT(user_data), DBUSMENU_CLIENT_PROP_TEXT_DIRECTION); g_variant_unref(textdir); + textdir = NULL; } /* Check the status if available */ @@ -1131,6 +1132,7 @@ menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data) g_object_notify(G_OBJECT(user_data), DBUSMENU_CLIENT_PROP_STATUS); g_variant_unref(status); + status = NULL; } /* Get the icon theme directories if available */ @@ -1145,6 +1147,7 @@ menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data) g_signal_emit(G_OBJECT(client), signals[ICON_THEME_DIRS], 0, priv->icon_dirs, TRUE); g_variant_unref(icon_dirs); + icon_dirs = NULL; } /* Get the icon theme directories if available */ -- cgit v1.2.3 From 8977e1ef7f5c2b7e98351ce942a4cac684f4ab05 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 16:19:50 -0500 Subject: Making sure the variant is appropriately wrapped --- libdbusmenu-glib/client.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 98329a1..7a37438 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1667,10 +1667,11 @@ events_to_builder (gpointer data, gpointer user_data) g_variant_builder_add_value(&tuple, g_variant_new_int32(edata->id)); g_variant_builder_add_value(&tuple, g_variant_new_string(edata->event)); - g_variant_builder_add_value(&tuple, edata->variant); + g_variant_builder_add_value(&tuple, g_variant_new_variant(edata->variant)); g_variant_builder_add_value(&tuple, g_variant_new_uint32(edata->timestamp)); - g_variant_builder_add_value(builder, g_variant_builder_end(&tuple)); + GVariant * vtuple = g_variant_builder_end(&tuple); + g_variant_builder_add_value(builder, vtuple); return; } -- cgit v1.2.3 From 73537ff947c6800ac432e5e70b0a1ab18f6f0a88 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 16:21:01 -0500 Subject: Making sure to init our error --- libdbusmenu-glib/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 7a37438..7bcce31 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1617,7 +1617,7 @@ event_group_cb (GObject * proxy, GAsyncResult * res, gpointer user_data) { GList * events = (GList *)user_data; - GError * error; + GError * error = NULL; GVariant * params; params = g_dbus_proxy_call_finish(G_DBUS_PROXY(proxy), res, &error); -- cgit v1.2.3 From 37eaae37fb9dc7163e3e91bc81debcca22ae46ff Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 16:23:39 -0500 Subject: Unpacking the tuple --- libdbusmenu-glib/server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index 2ba45d9..091b243 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -1723,6 +1723,7 @@ bus_event_group (DbusmenuServer * server, GVariant * params, GDBusMethodInvocati return; } + GVariant * events = g_variant_get_child_value(params, 0); gint32 id; gchar *etype; GVariant *data; @@ -1730,7 +1731,7 @@ bus_event_group (DbusmenuServer * server, GVariant * params, GDBusMethodInvocati GVariantIter iter; GVariantBuilder builder; - g_variant_iter_init(&iter, params); + g_variant_iter_init(&iter, events); g_variant_builder_init(&builder, G_VARIANT_TYPE("ai")); gboolean gotone = FALSE; @@ -1760,6 +1761,7 @@ bus_event_group (DbusmenuServer * server, GVariant * params, GDBusMethodInvocati } g_variant_unref(errors); + g_variant_unref(events); return; } -- cgit v1.2.3 From 1c810d69f0ac094ebc2b7094500d27d319372034 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 30 Mar 2012 17:26:22 -0500 Subject: Making sure to clear the idle so we queue again --- libdbusmenu-glib/client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 7bcce31..67beddb 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1688,6 +1688,7 @@ event_idle_cb (gpointer user_data) in the order they were called incase that matters. */ GList * levents = g_list_reverse(priv->events_to_go); priv->events_to_go = NULL; + priv->event_idle = 0; GVariantBuilder array; g_variant_builder_init(&array, G_VARIANT_TYPE("a(isvu)")); -- cgit v1.2.3 From 134cc4320738fb240d501892cafcf962eadda6ca Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 09:44:33 -0500 Subject: Add a property to whether we should group events or not --- libdbusmenu-glib/client.c | 7 ++++++- libdbusmenu-glib/client.h | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 67beddb..44b2902 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -52,7 +52,8 @@ enum { PROP_DBUSOBJECT, PROP_DBUSNAME, PROP_STATUS, - PROP_TEXT_DIRECTION + PROP_TEXT_DIRECTION, + PROP_GROUP_EVENTS }; /* Signals */ @@ -321,6 +322,10 @@ dbusmenu_client_class_init (DbusmenuClientClass *klass) "Signals which direction the default text direction is for the menus", DBUSMENU_TYPE_TEXT_DIRECTION, DBUSMENU_TEXT_DIRECTION_NONE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_GROUP_EVENTS, + g_param_spec_boolean(DBUSMENU_CLIENT_PROP_GROUP_EVENTS, "Whether or not multiple events should be grouped", + "Event grouping lowers the number of messages on DBus and will be set automatically based on the version to optimize traffic. It can be disabled for testing or other purposes.", + FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); if (dbusmenu_node_info == NULL) { GError * error = NULL; diff --git a/libdbusmenu-glib/client.h b/libdbusmenu-glib/client.h index d0fca32..ae22863 100644 --- a/libdbusmenu-glib/client.h +++ b/libdbusmenu-glib/client.h @@ -105,6 +105,12 @@ G_BEGIN_DECLS * String to access property #DbusmenuClient:text-direction */ #define DBUSMENU_CLIENT_PROP_TEXT_DIRECTION "text-direction" +/** + * DBUSMENU_CLIENT_PROP_GROUP_EVENTS: + * + * String to access property #DbusmenuClient:group-events + */ +#define DBUSMENU_CLIENT_PROP_GROUP_EVENTS "group-events" /** * DBUSMENU_CLIENT_TYPES_DEFAULT: -- cgit v1.2.3 From 5962851c31527fdb43a3d3b9b2c98ebeaaee88e8 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 09:48:46 -0500 Subject: Set and get the event grouping and notify if we change it --- libdbusmenu-glib/client.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 44b2902..6162c14 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -552,6 +552,9 @@ set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec) build_proxies(DBUSMENU_CLIENT(obj)); } break; + case PROP_GROUP_EVENTS: + priv->group_events = g_value_get_boolean(value); + break; default: g_warning("Unknown property %d.", id); return; @@ -578,6 +581,9 @@ get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec) case PROP_TEXT_DIRECTION: g_value_set_enum(value, priv->text_direction); break; + case PROP_GROUP_EVENTS: + g_value_set_boolean(value, priv->group_events); + break; default: g_warning("Unknown property %d.", id); return; @@ -1164,12 +1170,19 @@ menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data) remote_version = g_variant_get_uint32(version); } + gboolean old_group = priv->group_events; + /* Figure out if we can group the events or not */ if (remote_version >= 3) { priv->group_events = TRUE; } else { priv->group_events = FALSE; } + /* Notify listeners if we changed the value */ + if (old_group != priv->group_events) { + g_object_notify(G_OBJECT(client), DBUSMENU_CLIENT_PROP_GROUP_EVENTS); + } + g_variant_unref(version); version = NULL; } -- cgit v1.2.3 From 0afc1bc524816f08bcd459c96654ffc1dc6ddbb4 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 09:55:04 -0500 Subject: Adding a test that disables the event grouping --- .bzrignore | 2 + tests/Makefile.am | 24 ++++++ tests/test-glib-events-nogroup-client.c | 142 ++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 tests/test-glib-events-nogroup-client.c diff --git a/.bzrignore b/.bzrignore index 0073e93..bc1bf9c 100644 --- a/.bzrignore +++ b/.bzrignore @@ -257,3 +257,5 @@ tests/test-json-01.output.json genericmenuitem-enum-types.c genericmenuitem-enum-types.h libdbusmenu_gtk3_la-genericmenuitem-enum-types.lo +test-glib-events-nogroup +test-glib-events-nogroup-client diff --git a/tests/Makefile.am b/tests/Makefile.am index 82f6a9d..7ff2bb4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -8,6 +8,7 @@ EXTRA_DIST = TESTS = \ test-glib-objects-test \ test-glib-events \ + test-glib-events-nogroup \ test-glib-layout \ test-glib-properties \ test-glib-proxy \ @@ -45,6 +46,7 @@ check_PROGRAMS = \ test-glib-objects \ test-glib-events-client \ test-glib-events-server \ + test-glib-events-nogroup-client \ test-glib-layout-client \ test-glib-layout-server \ test-glib-properties-client \ @@ -200,6 +202,28 @@ test_glib_events_client_LDADD = \ ../libdbusmenu-glib/libdbusmenu-glib.la \ $(DBUSMENUGLIB_LIBS) +################################ +# Test Glib Events No Grouping +################################ + +test-glib-events-nogroup: test-glib-events-nogroup-client test-glib-events-server Makefile.am + @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ + @echo $(DBUS_RUNNER) --task ./test-glib-events-nogroup-client --task-name Client --task ./test-glib-events-server --task-name Server --ignore-return >> $@ + @chmod +x $@ + +test_glib_events_nogroup_client_SOURCES = \ + test-glib-events-nogroup-client.c + +test_glib_events_nogroup_client_CFLAGS = \ + -I $(srcdir)/.. \ + $(DBUSMENUGLIB_CFLAGS) -Wall -Werror + +test_glib_events_nogroup_client_LDADD = \ + ../libdbusmenu-glib/libdbusmenu-glib.la \ + $(DBUSMENUGLIB_LIBS) + ###################### # Test JSON ###################### diff --git a/tests/test-glib-events-nogroup-client.c b/tests/test-glib-events-nogroup-client.c new file mode 100644 index 0000000..f87660b --- /dev/null +++ b/tests/test-glib-events-nogroup-client.c @@ -0,0 +1,142 @@ +/* +A test for libdbusmenu to ensure its quality. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, 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 GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see . +*/ + +#include + +#include +#include + +#include "test-glib-submenu.h" + +#define TIMESTAMP_VALUE 54 +#define DATA_VALUE 32 +#define USER_VALUE 76 + +static GMainLoop * mainloop = NULL; +static gboolean passed = TRUE; +static gboolean first = TRUE; + +static void +event_status (DbusmenuClient * client, DbusmenuMenuitem * item, gchar * name, GVariant * data, guint timestamp, GError * error, gpointer user_data) +{ + g_debug("Event status: %s", error == NULL ? "Sent" : "Error"); + + if (timestamp != TIMESTAMP_VALUE) { + g_debug("Timestamp value pass fail got: %d", timestamp); + passed = FALSE; + g_main_loop_quit(mainloop); + return; + } + + if (g_variant_get_int32(data) != DATA_VALUE) { + g_debug("Data value pass fail got: %d", g_variant_get_int32(g_variant_get_child_value(data, 0))); + passed = FALSE; + g_main_loop_quit(mainloop); + return; + } + + if (GPOINTER_TO_INT(user_data) != USER_VALUE) { + g_debug("User value pass fail got: %d", GPOINTER_TO_INT(user_data)); + passed = FALSE; + g_main_loop_quit(mainloop); + return; + } + + if (first && error != NULL) { + passed = FALSE; + g_debug("First signal back failed."); + g_main_loop_quit(mainloop); + return; + } + + if (!first && error == NULL) { + passed = FALSE; + g_debug("Second signal didn't fail."); + g_main_loop_quit(mainloop); + return; + } + + if (!first && error != NULL) { + g_debug("Second signal failed: pass."); + g_main_loop_quit(mainloop); + return; + } + + first = FALSE; + dbusmenu_menuitem_handle_event(item, "clicked", data, timestamp); + return; +} + +static void +layout_updated (DbusmenuClient * client, gpointer user_data) +{ + g_debug("Layout Updated"); + + DbusmenuMenuitem * menuroot = dbusmenu_client_get_root(client); + if (menuroot == NULL) { + g_debug("Root is NULL?"); + return; + } + + g_object_set(G_OBJECT(client), + DBUSMENU_CLIENT_PROP_GROUP_EVENTS, FALSE, + NULL); + + GVariant * data = g_variant_new_int32(DATA_VALUE); + dbusmenu_menuitem_handle_event(menuroot, "clicked", data, TIMESTAMP_VALUE); + + return; +} + +static gboolean +timer_func (gpointer data) +{ + g_debug("Death timer. Oops."); + passed = FALSE; + g_main_loop_quit(mainloop); + return FALSE; +} + +int +main (int argc, char ** argv) +{ + g_type_init(); + + DbusmenuClient * client = dbusmenu_client_new("org.dbusmenu.test", "/org/test"); + g_signal_connect(G_OBJECT(client), DBUSMENU_CLIENT_SIGNAL_LAYOUT_UPDATED, G_CALLBACK(layout_updated), NULL); + g_signal_connect(G_OBJECT(client), DBUSMENU_CLIENT_SIGNAL_EVENT_RESULT, G_CALLBACK(event_status), GINT_TO_POINTER(USER_VALUE)); + + g_timeout_add_seconds(5, timer_func, client); + + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + g_debug("Main loop complete"); + g_object_unref(G_OBJECT(client)); + + if (passed) { + g_debug("Quiting"); + return 0; + } else { + g_debug("Quiting as we're a failure"); + return 1; + } +} -- cgit v1.2.3 From 4d3316b95941944d066d5ba50a05dbcc8140b216 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 10:37:33 -0500 Subject: Pulling out parts of about to show so that we have a core function there --- libdbusmenu-glib/client.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 6162c14..2657ada 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1805,6 +1805,26 @@ struct _about_to_show_t { gpointer cb_data; }; +/* Takes an about_to_show_t structure and calls the callback correctly + and updates the layout if needed. */ +static void +about_to_show_finish (about_to_show_t * data, gboolean need_update) +{ + /* If we need to update, do that first. */ + if (need_update) { + update_layout(data->client); + } + + if (data->cb != NULL) { + data->cb(data->cb_data); + } + + g_object_unref(data->client); + g_free(data); + + return; +} + /* Reports errors and responds to update request that were a result of sending the about to show signal. */ static void @@ -1828,18 +1848,7 @@ about_to_show_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) g_variant_unref(params); } - /* If we need to update, do that first. */ - if (need_update) { - update_layout(data->client); - } - - if (data->cb != NULL) { - data->cb(data->cb_data); - } - - g_object_unref(data->client); - g_free(data); - + about_to_show_finish(data, need_update); return; } -- cgit v1.2.3 From a16815864fb248612e23d231b791422eb295b67d Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 10:46:58 -0500 Subject: Set up the about-to-show task tracking variables --- libdbusmenu-glib/client.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 2657ada..e570272 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -109,8 +109,11 @@ struct _DbusmenuClientPrivate GStrv icon_dirs; gboolean group_events; - gulong event_idle; + guint event_idle; GList * events_to_go; /* type: event_data_t * */ + + guint about_to_show_idle; + GList * about_to_show_to_go; /* type: about_to_show_t * */ }; typedef struct _newItemPropData newItemPropData; @@ -184,6 +187,7 @@ static void menuproxy_name_changed_cb (GObject * object, GParamSpec * pspec, gpo static void menuproxy_signal_cb (GDBusProxy * proxy, gchar * sender, gchar * signal, GVariant * params, gpointer user_data); static void type_handler_destroy (gpointer user_data); static void event_data_end (event_data_t * eventd, GError * error); +static void about_to_show_finish_pntr (gpointer data, gpointer user_data); /* Globals */ static GDBusNodeInfo * dbusmenu_node_info = NULL; @@ -401,6 +405,9 @@ dbusmenu_client_init (DbusmenuClient *self) priv->event_idle = 0; priv->events_to_go = NULL; + priv->about_to_show_idle = 0; + priv->about_to_show_to_go = NULL; + return; } @@ -419,6 +426,11 @@ dbusmenu_client_dispose (GObject *object) priv->event_idle = 0; } + if (priv->about_to_show_idle != 0) { + g_source_remove(priv->about_to_show_idle); + priv->about_to_show_idle = 0; + } + if (priv->events_to_go != NULL) { g_warning("Getting to client dispose with events pending. This is odd. Probably there's a ref count problem somewhere, but we're going to be cool about it now and clean up. But there's probably a bug."); GError * error = g_error_new_literal(error_domain(), ERROR_DISPOSAL, "Client disposed before event signal returned"); @@ -428,6 +440,13 @@ dbusmenu_client_dispose (GObject *object) g_error_free(error); } + if (priv->about_to_show_to_go != NULL) { + g_warning("Getting to client dispose with about_to_show's pending. This is odd. Probably there's a ref count problem somewhere, but we're going to be cool about it now and clean up. But there's probably a bug."); + g_list_foreach(priv->about_to_show_to_go, about_to_show_finish_pntr, GINT_TO_POINTER(FALSE)); + g_list_free(priv->about_to_show_to_go); + priv->about_to_show_to_go = NULL; + } + /* Only used for queueing up a new command, so we can just drop this array. */ if (priv->delayed_property_list != NULL) { @@ -1825,6 +1844,14 @@ about_to_show_finish (about_to_show_t * data, gboolean need_update) return; } +/* A little function to match prototypes and make sure to convert from + a pointer to an int correctly */ +static void +about_to_show_finish_pntr (gpointer data, gpointer user_data) +{ + return about_to_show_finish((about_to_show_t *)data, GPOINTER_TO_INT(user_data)); +} + /* Reports errors and responds to update request that were a result of sending the about to show signal. */ static void -- cgit v1.2.3 From 8c3fd4afb6b87184abb15567a93a7f426e6ecd41 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 11:22:36 -0500 Subject: Setup our idle if we're grouping the events --- libdbusmenu-glib/client.c | 45 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index e570272..2ee081d 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1852,6 +1852,19 @@ about_to_show_finish_pntr (gpointer data, gpointer user_data) return about_to_show_finish((about_to_show_t *)data, GPOINTER_TO_INT(user_data)); } +/* Function that gets called with all the queued about_to_show messages, let's + get these guys on the bus! */ +static gboolean +about_to_show_idle (gpointer user_data) +{ + DbusmenuClient * client = DBUSMENU_CLIENT(user_data); + DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client); + + priv->about_to_show_idle = 0; + + return FALSE; +} + /* Reports errors and responds to update request that were a result of sending the about to show signal. */ static void @@ -1896,14 +1909,30 @@ dbusmenu_client_send_about_to_show(DbusmenuClient * client, gint id, void (*cb)( data->cb_data = cb_data; g_object_ref(client); - g_dbus_proxy_call(priv->menuproxy, - "AboutToShow", - g_variant_new("(i)", id), - G_DBUS_CALL_FLAGS_NONE, - -1, /* timeout */ - NULL, /* cancellable */ - about_to_show_cb, - data); + if (priv->group_events) { + priv->about_to_show_to_go = g_list_prepend(priv->about_to_show_to_go, data); + + if (priv->about_to_show_idle == 0) { + priv->about_to_show_idle = g_idle_add(about_to_show_idle, client); + } + } else { + /* If there's no callback we don't need this data, let's + clean it up in a consistent way */ + if (cb == NULL) { + about_to_show_finish(data, FALSE); + data = NULL; + } + + g_dbus_proxy_call(priv->menuproxy, + "AboutToShow", + g_variant_new("(i)", id), + G_DBUS_CALL_FLAGS_NONE, + -1, /* timeout */ + NULL, /* cancellable */ + about_to_show_cb, + data); + } + return; } -- cgit v1.2.3 From acb279c7302c663537fdc1827fba7564d6e58f27 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 11:48:06 -0500 Subject: Fleshing out the idle handler for about to show --- libdbusmenu-glib/client.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 2ee081d..e9801b0 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1819,6 +1819,7 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name typedef struct _about_to_show_t about_to_show_t; struct _about_to_show_t { + gint id; DbusmenuClient * client; void (*cb) (gpointer data); gpointer cb_data; @@ -1852,6 +1853,44 @@ about_to_show_finish_pntr (gpointer data, gpointer user_data) return about_to_show_finish((about_to_show_t *)data, GPOINTER_TO_INT(user_data)); } +/* Respond to the DBus message from sending a bunch of about-to-show events + to the server */ +static void +about_to_show_group_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) +{ + + + return; +} + +/* Check to see if this about to show entry has a callback associated + with it */ +static void +about_to_show_idle_callbacks (gpointer data, gpointer user_data) +{ + about_to_show_t * abts = (about_to_show_t *)data; + gboolean * got_callbacks = (gboolean *)user_data; + + if (abts->cb != NULL) { + *got_callbacks = TRUE; + } + + return; +} + +/* Take the ID out of the about to show structure and put it into the + variant builder */ +static void +about_to_show_idle_ids (gpointer data, gpointer user_data) +{ + about_to_show_t * abts = (about_to_show_t *)data; + GVariantBuilder * builder = (GVariantBuilder *)user_data; + + g_variant_builder_add_value(builder, g_variant_new_int32(abts->id)); + + return; +} + /* Function that gets called with all the queued about_to_show messages, let's get these guys on the bus! */ static gboolean @@ -1860,7 +1899,41 @@ about_to_show_idle (gpointer user_data) DbusmenuClient * client = DBUSMENU_CLIENT(user_data); DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client); + /* Reset our object global props and take ownership of these entries */ priv->about_to_show_idle = 0; + GList * showers = g_list_reverse(priv->about_to_show_to_go); + priv->about_to_show_to_go = NULL; + + /* Figure out if we've got any callbacks */ + gboolean got_callbacks = FALSE; + g_list_foreach(showers, about_to_show_idle_callbacks, &got_callbacks); + + /* Build a list of the IDs */ + GVariantBuilder idarray; + g_variant_builder_init(&idarray, G_VARIANT_TYPE("ai")); + g_list_foreach(showers, about_to_show_idle_ids, &idarray); + GVariant * ids = g_variant_builder_end(&idarray); + + /* Setup our callbacks */ + GAsyncReadyCallback cb = NULL; + gpointer cb_data = NULL; + if (got_callbacks) { + cb = about_to_show_group_cb; + cb_data = showers; + } else { + g_list_foreach(showers, about_to_show_finish_pntr, GINT_TO_POINTER(FALSE)); + g_list_free(showers); + } + + /* Let's call it! */ + g_dbus_proxy_call(priv->menuproxy, + "AboutToShowGroup", + g_variant_new_tuple(&ids, 1), + G_DBUS_CALL_FLAGS_NONE, + -1, /* timeout */ + NULL, /* cancellable */ + cb, + cb_data); return FALSE; } @@ -1904,6 +1977,7 @@ dbusmenu_client_send_about_to_show(DbusmenuClient * client, gint id, void (*cb)( g_return_if_fail(priv != NULL); about_to_show_t * data = g_new0(about_to_show_t, 1); + data->id = id; data->client = client; data->cb = cb; data->cb_data = cb_data; -- cgit v1.2.3 From d5eb39fd5b2944ec416bda0cc0d0528b0555bf33 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 11:57:10 -0500 Subject: Fill out the group callback to update if we need it --- libdbusmenu-glib/client.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index e9801b0..2828a1f 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1858,7 +1858,37 @@ about_to_show_finish_pntr (gpointer data, gpointer user_data) static void about_to_show_group_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) { + GError * error = NULL; + GList * showers = (GList *)userdata; + GVariant * params = NULL; + + params = g_dbus_proxy_call_finish(G_DBUS_PROXY(proxy), res, &error); + + if (error != NULL) { + g_warning("Unable to send about_to_show_group: %s", error->message); + /* Note: we're just ensuring only the callback gets called */ + g_error_free(error); + error = NULL; + } else { + GVariant * updates = g_variant_get_child_value(params, 0); + GVariantIter iter; + + /* Okay, so this is kinda interesting. We actually don't care which + entries asked us to update the structure, as it's quite simply a + single structure. So if we have any ask, we get the update once to + avoid itterating through all the structures. */ + if (g_variant_iter_init(&iter, updates) > 0) { + about_to_show_t * first = (about_to_show_t *)showers->data; + update_layout(first->client); + } + + g_variant_unref(updates); + g_variant_unref(params); + params = NULL; + } + g_list_foreach(showers, about_to_show_finish_pntr, GINT_TO_POINTER(FALSE)); + g_list_free(showers); return; } -- cgit v1.2.3 From 5ca8057eec7cabefc72c91f7df47a9ceb071d3f9 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 14:49:21 -0500 Subject: Adding the group events property --- docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt b/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt index 7f11278..7804937 100644 --- a/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt +++ b/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt @@ -9,6 +9,7 @@ DBUSMENU_CLIENT_SIGNAL_ITEM_ACTIVATE DBUSMENU_CLIENT_SIGNAL_ICON_THEME_DIRS_CHANGED DBUSMENU_CLIENT_PROP_DBUS_NAME DBUSMENU_CLIENT_PROP_DBUS_OBJECT +DBUSMENU_CLIENT_PROP_GROUP_EVENTS DBUSMENU_CLIENT_PROP_STATUS DBUSMENU_CLIENT_PROP_TEXT_DIRECTION DBUSMENU_CLIENT_TYPES_DEFAULT -- cgit v1.2.3 -- cgit v1.2.3 From af0566fcf27c1ce3bc092e88b306353aad4ba2c1 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 23:22:07 -0500 Subject: Switching to GQueue --- libdbusmenu-glib/client.c | 64 ++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 2828a1f..4595865 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -110,10 +110,10 @@ struct _DbusmenuClientPrivate gboolean group_events; guint event_idle; - GList * events_to_go; /* type: event_data_t * */ + GQueue * events_to_go; /* type: event_data_t * */ guint about_to_show_idle; - GList * about_to_show_to_go; /* type: about_to_show_t * */ + GQueue * about_to_show_to_go; /* type: about_to_show_t * */ }; typedef struct _newItemPropData newItemPropData; @@ -434,16 +434,16 @@ dbusmenu_client_dispose (GObject *object) if (priv->events_to_go != NULL) { g_warning("Getting to client dispose with events pending. This is odd. Probably there's a ref count problem somewhere, but we're going to be cool about it now and clean up. But there's probably a bug."); GError * error = g_error_new_literal(error_domain(), ERROR_DISPOSAL, "Client disposed before event signal returned"); - g_list_foreach(priv->events_to_go, (GFunc)event_data_end, error); - g_list_free(priv->events_to_go); + g_queue_foreach(priv->events_to_go, (GFunc)event_data_end, error); + g_queue_free(priv->events_to_go); priv->events_to_go = NULL; g_error_free(error); } if (priv->about_to_show_to_go != NULL) { g_warning("Getting to client dispose with about_to_show's pending. This is odd. Probably there's a ref count problem somewhere, but we're going to be cool about it now and clean up. But there's probably a bug."); - g_list_foreach(priv->about_to_show_to_go, about_to_show_finish_pntr, GINT_TO_POINTER(FALSE)); - g_list_free(priv->about_to_show_to_go); + g_queue_foreach(priv->about_to_show_to_go, about_to_show_finish_pntr, GINT_TO_POINTER(FALSE)); + g_queue_free(priv->about_to_show_to_go); priv->about_to_show_to_go = NULL; } @@ -1652,7 +1652,7 @@ event_data_find (gconstpointer data, gconstpointer user_data) static void event_group_cb (GObject * proxy, GAsyncResult * res, gpointer user_data) { - GList * events = (GList *)user_data; + GQueue * events = (GQueue *)user_data; GError * error = NULL; GVariant * params; @@ -1661,8 +1661,8 @@ event_group_cb (GObject * proxy, GAsyncResult * res, gpointer user_data) if (error != NULL) { /* If we got an actual DBus error, we should just pass that along and finish up */ - g_list_foreach(events, (GFunc)event_data_end, error); - g_list_free(events); + g_queue_foreach(events, (GFunc)event_data_end, error); + g_queue_free(events); events = NULL; return; } @@ -1673,12 +1673,12 @@ event_group_cb (GObject * proxy, GAsyncResult * res, gpointer user_data) g_variant_iter_init(&iter, array); while (g_variant_iter_loop(&iter, "i", &id)) { - GList * item = g_list_find_custom(events, GINT_TO_POINTER(id), event_data_find); + GList * item = g_queue_find_custom(events, GINT_TO_POINTER(id), event_data_find); if (item != NULL) { GError * iderror = g_error_new(error_domain(), ERROR_ID_NOT_FOUND, "Unable to find ID: %d", id); event_data_end((event_data_t *)item->data, iderror); - events = g_list_delete_link(events, item); + g_queue_delete_link(events, item); g_error_free(iderror); } } @@ -1687,8 +1687,8 @@ event_group_cb (GObject * proxy, GAsyncResult * res, gpointer user_data) g_variant_unref(params); /* If we have any left send non-error responses */ - g_list_foreach(events, (GFunc)event_data_end, NULL); - g_list_free(events); + g_queue_foreach(events, (GFunc)event_data_end, NULL); + g_queue_free(events); return; } @@ -1723,13 +1723,13 @@ event_idle_cb (gpointer user_data) /* We use prepend for speed, but now we want to have them in the order they were called incase that matters. */ - GList * levents = g_list_reverse(priv->events_to_go); + GQueue * levents = priv->events_to_go; priv->events_to_go = NULL; priv->event_idle = 0; GVariantBuilder array; g_variant_builder_init(&array, G_VARIANT_TYPE("a(isvu)")); - g_list_foreach(levents, events_to_builder, &array); + g_queue_foreach(levents, events_to_builder, &array); GVariant * vevents = g_variant_builder_end(&array); if (g_signal_has_handler_pending (client, signals[EVENT_RESULT], 0, TRUE)) { @@ -1748,8 +1748,8 @@ event_idle_cb (gpointer user_data) 1000, /* timeout */ NULL, /* cancellable */ NULL, NULL); - g_list_foreach(levents, (GFunc)event_data_end, NULL); - g_list_free(levents); + g_queue_foreach(levents, (GFunc)event_data_end, NULL); + g_queue_free(levents); } return FALSE; @@ -1807,7 +1807,11 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name menuitem_call_cb, edata); } else { - priv->events_to_go = g_list_prepend(priv->events_to_go, edata); + if (priv->events_to_go == NULL) { + priv->events_to_go = g_queue_new(); + } + + g_queue_push_tail(priv->events_to_go, edata); if (priv->event_idle == 0) { priv->event_idle = g_idle_add(event_idle_cb, client); @@ -1859,7 +1863,7 @@ static void about_to_show_group_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) { GError * error = NULL; - GList * showers = (GList *)userdata; + GQueue * showers = (GQueue *)userdata; GVariant * params = NULL; params = g_dbus_proxy_call_finish(G_DBUS_PROXY(proxy), res, &error); @@ -1878,7 +1882,7 @@ about_to_show_group_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) single structure. So if we have any ask, we get the update once to avoid itterating through all the structures. */ if (g_variant_iter_init(&iter, updates) > 0) { - about_to_show_t * first = (about_to_show_t *)showers->data; + about_to_show_t * first = (about_to_show_t *)g_queue_peek_head(showers); update_layout(first->client); } @@ -1887,8 +1891,8 @@ about_to_show_group_cb (GObject * proxy, GAsyncResult * res, gpointer userdata) params = NULL; } - g_list_foreach(showers, about_to_show_finish_pntr, GINT_TO_POINTER(FALSE)); - g_list_free(showers); + g_queue_foreach(showers, about_to_show_finish_pntr, GINT_TO_POINTER(FALSE)); + g_queue_free(showers); return; } @@ -1931,17 +1935,17 @@ about_to_show_idle (gpointer user_data) /* Reset our object global props and take ownership of these entries */ priv->about_to_show_idle = 0; - GList * showers = g_list_reverse(priv->about_to_show_to_go); + GQueue * showers = priv->about_to_show_to_go; priv->about_to_show_to_go = NULL; /* Figure out if we've got any callbacks */ gboolean got_callbacks = FALSE; - g_list_foreach(showers, about_to_show_idle_callbacks, &got_callbacks); + g_queue_foreach(showers, about_to_show_idle_callbacks, &got_callbacks); /* Build a list of the IDs */ GVariantBuilder idarray; g_variant_builder_init(&idarray, G_VARIANT_TYPE("ai")); - g_list_foreach(showers, about_to_show_idle_ids, &idarray); + g_queue_foreach(showers, about_to_show_idle_ids, &idarray); GVariant * ids = g_variant_builder_end(&idarray); /* Setup our callbacks */ @@ -1951,8 +1955,8 @@ about_to_show_idle (gpointer user_data) cb = about_to_show_group_cb; cb_data = showers; } else { - g_list_foreach(showers, about_to_show_finish_pntr, GINT_TO_POINTER(FALSE)); - g_list_free(showers); + g_queue_foreach(showers, about_to_show_finish_pntr, GINT_TO_POINTER(FALSE)); + g_queue_free(showers); } /* Let's call it! */ @@ -2014,7 +2018,11 @@ dbusmenu_client_send_about_to_show(DbusmenuClient * client, gint id, void (*cb)( g_object_ref(client); if (priv->group_events) { - priv->about_to_show_to_go = g_list_prepend(priv->about_to_show_to_go, data); + if (priv->about_to_show_to_go == NULL) { + priv->about_to_show_to_go = g_queue_new(); + } + + g_queue_push_tail(priv->about_to_show_to_go, data); if (priv->about_to_show_idle == 0) { priv->about_to_show_idle = g_idle_add(about_to_show_idle, client); -- cgit v1.2.3 From 70c8f8431d70481b8fcf90787f6987250ad84889 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 3 Apr 2012 23:23:00 -0500 Subject: Fixing a cut-and-paste comment --- libdbusmenu-glib/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 4595865..34f8b8d 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -1180,7 +1180,7 @@ menuproxy_build_cb (GObject * object, GAsyncResult * res, gpointer user_data) icon_dirs = NULL; } - /* Get the icon theme directories if available */ + /* Get the dbusmenu protocol version if available */ GVariant * version = g_dbus_proxy_get_cached_property(priv->menuproxy, "Version"); if (version != NULL) { guint32 remote_version = 0; -- cgit v1.2.3