aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-glib
diff options
context:
space:
mode:
Diffstat (limited to 'libdbusmenu-glib')
-rw-r--r--libdbusmenu-glib/Makefile.am1
-rw-r--r--libdbusmenu-glib/client.c98
-rw-r--r--libdbusmenu-glib/menuitem.c6
-rw-r--r--libdbusmenu-glib/server.c66
4 files changed, 118 insertions, 53 deletions
diff --git a/libdbusmenu-glib/Makefile.am b/libdbusmenu-glib/Makefile.am
index 219ddcf..b2e796c 100644
--- a/libdbusmenu-glib/Makefile.am
+++ b/libdbusmenu-glib/Makefile.am
@@ -6,6 +6,7 @@ EXTRA_DIST = \
clean-namespaces.xslt \
dbusmenu-glib-0.4.pc.in \
dbus-menu.xml \
+ dbus-menu-clean.xml \
client-marshal.list \
menuitem-marshal.list \
server-marshal.list
diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c
index e64d923..7d96db3 100644
--- a/libdbusmenu-glib/client.c
+++ b/libdbusmenu-glib/client.c
@@ -601,64 +601,66 @@ get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data)
listener->callback(NULL, error, listener->user_data);
}
g_error_free(error);
- goto out;
}
/* Callback all the folks we can find */
- GVariant * parent = g_variant_get_child_value(params, 0);
- GVariantIter iter;
- g_variant_iter_init(&iter, parent);
- GVariant * child;
- while ((child = g_variant_iter_next_value(&iter)) != NULL) {
- if (g_strcmp0(g_variant_get_type_string(child), "(ia{sv})") != 0) {
- g_warning("Properties return signature is not '(ia{sv})' it is '%s'", g_variant_get_type_string(child));
- g_variant_unref(child);
- continue;
- }
+ if (error == NULL) {
+ GVariant * parent = g_variant_get_child_value(params, 0);
+ GVariantIter iter;
+ g_variant_iter_init(&iter, parent);
+ GVariant * child;
+ while ((child = g_variant_iter_next_value(&iter)) != NULL) {
+ if (g_strcmp0(g_variant_get_type_string(child), "(ia{sv})") != 0) {
+ g_warning("Properties return signature is not '(ia{sv})' it is '%s'", g_variant_get_type_string(child));
+ g_variant_unref(child);
+ continue;
+ }
- GVariant * idv = g_variant_get_child_value(child, 0);
- gint id = g_variant_get_int32(idv);
- g_variant_unref(idv);
+ GVariant * idv = g_variant_get_child_value(child, 0);
+ gint id = g_variant_get_int32(idv);
+ g_variant_unref(idv);
- GVariant * properties = g_variant_get_child_value(child, 1);
+ GVariant * properties = g_variant_get_child_value(child, 1);
- properties_listener_t * listener = find_listener(listeners, 0, id);
- if (listener == NULL) {
- g_warning("Unable to find listener for ID %d", id);
+ properties_listener_t * listener = find_listener(listeners, 0, id);
+ if (listener == NULL) {
+ g_warning("Unable to find listener for ID %d", id);
+ g_variant_unref(properties);
+ g_variant_unref(child);
+ continue;
+ }
+
+ if (!listener->replied) {
+ listener->callback(properties, NULL, listener->user_data);
+ listener->replied = TRUE;
+ } else {
+ g_warning("Odd, we've already replied to the listener on ID %d", id);
+ }
g_variant_unref(properties);
g_variant_unref(child);
- continue;
- }
-
- if (!listener->replied) {
- listener->callback(properties, NULL, listener->user_data);
- listener->replied = TRUE;
- } else {
- g_warning("Odd, we've already replied to the listener on ID %d", id);
}
- g_variant_unref(properties);
- g_variant_unref(child);
+ g_variant_unref(parent);
+ g_variant_unref(params);
}
- g_variant_unref(parent);
- g_variant_unref(params);
/* Provide errors for those who we can't */
- GError * localerror = NULL;
- 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);
- if (localerror == NULL) {
- g_set_error_literal(&localerror, error_domain(), 0, "Error getting properties for ID");
+ if (error == NULL && listeners->len > 0) {
+ GError * localerror = NULL;
+ 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);
+ if (localerror == NULL) {
+ g_set_error_literal(&localerror, error_domain(), 0, "Error getting properties for ID");
+ }
+ listener->callback(NULL, localerror, listener->user_data);
}
- listener->callback(NULL, localerror, listener->user_data);
}
- }
- if (localerror != NULL) {
- g_error_free(localerror);
+ if (localerror != NULL) {
+ g_error_free(localerror);
+ }
}
-out:
/* Clean up */
g_array_free(listeners, TRUE);
g_object_unref(cbdata->client);
@@ -1538,6 +1540,18 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name
variant = g_variant_new_int32(0);
}
+ /* 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,
+ "Event",
+ g_variant_new("(isvu)", id, name, variant, timestamp),
+ G_DBUS_CALL_FLAGS_NONE,
+ 1000, /* timeout */
+ NULL, /* cancellable */
+ NULL, NULL);
+ return;
+ }
+
event_data_t * edata = g_new0(event_data_t, 1);
edata->client = client;
g_object_ref(client);
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c
index 18db4ef..c81c36e 100644
--- a/libdbusmenu-glib/menuitem.c
+++ b/libdbusmenu-glib/menuitem.c
@@ -1253,7 +1253,7 @@ dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * pro
becuse it has been unref'd when replaced in the hash
table. But the fact that there was a value is
the imporant part. */
- if (!inhash || replaced) {
+ if (replaced) {
GVariant * signalval = value;
if (signalval == NULL) {
@@ -1462,8 +1462,8 @@ dbusmenu_menuitem_property_remove (DbusmenuMenuitem * mi, const gchar * property
* by the menuitem but the list is not and should be freed using
* g_list_free() when the calling function is done with it.
*
- * Return value: (transfer container): A list of strings or NULL if there are
- * none.
+ * Return value: (transfer container) (element-type utf8): A list of
+ * strings or NULL if there are none.
*/
GList *
dbusmenu_menuitem_properties_list (DbusmenuMenuitem * mi)
diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c
index 524e777..1b4ce95 100644
--- a/libdbusmenu-glib/server.c
+++ b/libdbusmenu-glib/server.c
@@ -64,6 +64,8 @@ struct _DbusmenuServerPrivate
GArray * prop_array;
guint property_idle;
+
+ GHashTable * lookup_cache;
};
#define DBUSMENU_SERVER_GET_PRIVATE(o) (DBUSMENU_SERVER(o)->priv)
@@ -378,6 +380,8 @@ dbusmenu_server_init (DbusmenuServer *self)
priv->find_server_signal = 0;
priv->dbus_registration = 0;
+ priv->lookup_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref);
+
default_text_direction(self);
priv->status = DBUSMENU_STATUS_NORMAL;
priv->icon_dirs = NULL;
@@ -450,10 +454,50 @@ dbusmenu_server_finalize (GObject *object)
priv->icon_dirs = NULL;
}
+ if (priv->lookup_cache) {
+ g_hash_table_destroy(priv->lookup_cache);
+ priv->lookup_cache = NULL;
+ }
+
G_OBJECT_CLASS (dbusmenu_server_parent_class)->finalize (object);
return;
}
+static DbusmenuMenuitem *
+lookup_menuitem_by_id (DbusmenuServer * server, gint id)
+{
+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
+
+ DbusmenuMenuitem *res = (DbusmenuMenuitem *) g_hash_table_lookup(priv->lookup_cache, GINT_TO_POINTER(id));
+ if (!res && id == 0) {
+ return priv->root;
+ }
+
+ return res;
+}
+
+static void
+cache_remove_entries_for_menuitem (GHashTable * cache, DbusmenuMenuitem * item)
+{
+ g_hash_table_remove(cache, GINT_TO_POINTER(dbusmenu_menuitem_get_id(item)));
+
+ GList *child, *children = dbusmenu_menuitem_get_children(item);
+ for (child = children; child != NULL; child = child->next) {
+ cache_remove_entries_for_menuitem(cache, child->data);
+ }
+}
+
+static void
+cache_add_entries_for_menuitem (GHashTable * cache, DbusmenuMenuitem * item)
+{
+ g_hash_table_insert(cache, GINT_TO_POINTER(dbusmenu_menuitem_get_id(item)), g_object_ref(item));
+
+ GList *child, *children = dbusmenu_menuitem_get_children(item);
+ for (child = children; child != NULL; child = child->next) {
+ cache_add_entries_for_menuitem(cache, child->data);
+ }
+}
+
static void
set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
{
@@ -480,6 +524,7 @@ set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
if (priv->root != NULL) {
dbusmenu_menuitem_foreach(priv->root, menuitem_signals_remove, obj);
dbusmenu_menuitem_set_root(priv->root, FALSE);
+ cache_remove_entries_for_menuitem(priv->lookup_cache, priv->root);
GList * properties = dbusmenu_menuitem_properties_list(priv->root);
GList * iter;
@@ -495,6 +540,7 @@ set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
priv->root = DBUSMENU_MENUITEM(g_value_get_object(value));
if (priv->root != NULL) {
g_object_ref(G_OBJECT(priv->root));
+ cache_add_entries_for_menuitem(priv->lookup_cache, priv->root);
dbusmenu_menuitem_set_root(priv->root, TRUE);
dbusmenu_menuitem_foreach(priv->root, menuitem_signals_create, obj);
@@ -1161,6 +1207,7 @@ static void
menuitem_child_added (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, guint pos, DbusmenuServer * server)
{
menuitem_signals_create(child, server);
+ cache_add_entries_for_menuitem(server->priv->lookup_cache, child);
g_list_foreach(dbusmenu_menuitem_get_children(child), added_check_children, server);
layout_update_signal(server);
@@ -1171,6 +1218,7 @@ static void
menuitem_child_removed (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, DbusmenuServer * server)
{
menuitem_signals_remove(child, server);
+ cache_remove_entries_for_menuitem(server->priv->lookup_cache, child);
layout_update_signal(server);
return;
}
@@ -1259,7 +1307,7 @@ bus_get_layout (DbusmenuServer * server, GVariant * params, GDBusMethodInvocatio
GVariant * items = NULL;
if (priv->root != NULL) {
- DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, parent);
+ DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, parent);
if (mi != NULL) {
items = dbusmenu_menuitem_build_variant(mi, props, recurse);
@@ -1318,7 +1366,7 @@ bus_get_property (DbusmenuServer * server, GVariant * params, GDBusMethodInvocat
g_variant_get(params, "(i&s)", &id, &property);
- DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
+ DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id);
if (mi == NULL) {
g_dbus_method_invocation_return_error(invocation,
@@ -1361,7 +1409,7 @@ bus_get_properties (DbusmenuServer * server, GVariant * params, GDBusMethodInvoc
gint32 id;
g_variant_get(params, "(i)", &id);
- DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
+ DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id);
if (mi == NULL) {
g_dbus_method_invocation_return_error(invocation,
@@ -1424,7 +1472,7 @@ bus_get_group_properties (DbusmenuServer * server, GVariant * params, GDBusMetho
gint32 id;
while (g_variant_iter_loop(ids, "i", &id)) {
- DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
+ DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id);
if (mi == NULL) continue;
if (!builder_init) {
@@ -1523,7 +1571,7 @@ bus_get_children (DbusmenuServer * server, GVariant * params, GDBusMethodInvocat
return;
}
- DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
+ DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id);
if (mi == NULL) {
g_dbus_method_invocation_return_error(invocation,
@@ -1606,7 +1654,7 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i
g_variant_get(params, "(isvu)", &id, &etype, &data, &ts);
- DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
+ DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id);
if (mi == NULL) {
g_dbus_method_invocation_return_error(invocation,
@@ -1626,7 +1674,9 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i
g_timeout_add(0, event_local_handler, event_data);
- g_dbus_method_invocation_return_value(invocation, NULL);
+ 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);
+ }
}
return;
@@ -1648,7 +1698,7 @@ bus_about_to_show (DbusmenuServer * server, GVariant * params, GDBusMethodInvoca
gint32 id;
g_variant_get(params, "(i)", &id);
- DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
+ DbusmenuMenuitem * mi = lookup_menuitem_by_id(server, id);
if (mi == NULL) {
g_dbus_method_invocation_return_error(invocation,