aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac7
-rw-r--r--libdbusmenu-glib/Makefile.am1
-rw-r--r--libdbusmenu-glib/server.c62
-rw-r--r--libdbusmenu-gtk/client.c14
-rw-r--r--tests/Makefile.am21
-rw-r--r--tests/json-loader.c24
-rw-r--r--tests/test-json-client.c23
-rwxr-xr-xtests/test-json-instruction-count6
-rw-r--r--tests/test-json-server.c18
-rw-r--r--tools/dbusmenu-dumper.c54
10 files changed, 178 insertions, 52 deletions
diff --git a/configure.ac b/configure.ac
index 42c5b3d..e397cb5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,11 +1,11 @@
-AC_INIT(libdbusmenu, 0.5.95, ted@canonical.com)
+AC_INIT(libdbusmenu, 0.5.96, ted@canonical.com)
AC_COPYRIGHT([Copyright 2009,2010 Canonical])
AC_PREREQ(2.62)
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(libdbusmenu, 0.5.95, [-Wno-portability])
+AM_INIT_AUTOMAKE(libdbusmenu, 0.5.96, [-Wno-portability])
AM_MAINTAINER_MODE
@@ -118,7 +118,8 @@ AM_CONDITIONAL([WANT_TESTS], [test "x$enable_tests" != "xno"])
AS_IF([test "x$enable_tests" != "xno"],[
PKG_CHECK_MODULES(DBUSMENUTESTS, json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION
- gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION,
+ gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION
+ valgrind,
[have_tests=yes]
)
])
diff --git a/libdbusmenu-glib/Makefile.am b/libdbusmenu-glib/Makefile.am
index 6fc3fb8..fa7c8cb 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/server.c b/libdbusmenu-glib/server.c
index 0eff073..e67ec58 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)
@@ -392,6 +394,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;
@@ -464,10 +468,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)
{
@@ -494,6 +538,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;
@@ -509,6 +554,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);
@@ -1175,6 +1221,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);
@@ -1185,6 +1232,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;
}
@@ -1273,7 +1321,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);
@@ -1332,7 +1380,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,
@@ -1375,7 +1423,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,
@@ -1438,7 +1486,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) {
@@ -1537,7 +1585,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,
@@ -1620,7 +1668,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,
@@ -1673,7 +1721,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,
diff --git a/libdbusmenu-gtk/client.c b/libdbusmenu-gtk/client.c
index f507a56..60af93f 100644
--- a/libdbusmenu-gtk/client.c
+++ b/libdbusmenu-gtk/client.c
@@ -787,22 +787,13 @@ menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * variant, Db
process_disposition(mi, gmi, variant, gtkclient);
} else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC)) {
process_a11y_desc(mi, gmi, variant, gtkclient);
+ } else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_SHORTCUT)) {
+ refresh_shortcut(gtkclient, mi);
}
return;
}
-/* Special handler for the shortcut changing as we need to have the
- client for that one to get the accel group. */
-static void
-menu_shortcut_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * value, DbusmenuGtkClient * client)
-{
- if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_SHORTCUT)) {
- refresh_shortcut(client, mi);
- }
- return;
-}
-
/* The new menuitem signal only happens if we don't have a type handler
for the type of the item. This should be an error condition and we're
printing out a message. */
@@ -918,7 +909,6 @@ dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem *
/* DbusmenuMenuitem signals */
g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_change_cb), client);
- g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_shortcut_change_cb), client);
g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(delete_child), client);
g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(move_child), client);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6824c1c..82f6a9d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -16,7 +16,8 @@ TESTS = \
if WANT_DBUSMENUDUMPER
TESTS += \
- test-json
+ test-json \
+ test-json-instruction
endif
if WANT_LIBDBUSMENUGTK
@@ -208,7 +209,7 @@ test-json: test-json-client test-json-server Makefile.am
@echo export UBUNTU_MENUPROXY="" >> $@
@echo export G_DEBUG=fatal_criticals >> $@
@echo $(XVFB_RUN) >> $@
- @echo $(DBUS_RUNNER) --task ./test-json-client --task-name Client --parameter $(top_builddir)/tools/dbusmenu-dumper --parameter test-json-01.output.json --ignore-return --task ./test-json-server --task-name Server --parameter $(srcdir)/test-json-01.json --ignore-return >> $@
+ @echo $(DBUS_RUNNER) --task ./test-json-client --wait-for org.dbusmenu.test --task-name Client --parameter $(top_builddir)/tools/dbusmenu-dumper --parameter test-json-01.output.json --ignore-return --task ./test-json-server --task-name Server --parameter $(srcdir)/test-json-01.json --ignore-return >> $@
@echo diff $(srcdir)/test-json-01.json test-json-01.output.json \> /dev/null >> $@
@chmod +x $@
@@ -242,6 +243,22 @@ test_json_client_LDADD = \
$(DBUSMENUTESTS_LIBS) \
$(DBUSMENUGLIB_LIBS)
+#########################
+# Test JSON Instructions
+#########################
+
+test-json-instruction: test-json-client test-json-server test-json-instruction-count Makefile.am
+ @echo "#!/bin/bash" > $@
+ @echo export UBUNTU_MENUPROXY="" >> $@
+ @echo export G_DEBUG=fatal_criticals >> $@
+ @echo $(XVFB_RUN) >> $@
+ @echo $(DBUS_RUNNER) --task $(builddir)/test-json-client --wait-for org.dbusmenu.test --task-name Client --parameter $(top_builddir)/tools/dbusmenu-dumper --parameter /dev/null --ignore-return --task libtool --parameter --mode=execute --parameter $(srcdir)/test-json-instruction-count --parameter $(builddir)/test-json-server --task-name Server --parameter $(srcdir)/test-json-01.json --ignore-return >> $@
+ @chmod +x $@
+
+EXTRA_DIST += \
+ test-json-instruction-count
+
+
######################
# Test Glib Submenu
######################
diff --git a/tests/json-loader.c b/tests/json-loader.c
index 7f0ec8e..94982c4 100644
--- a/tests/json-loader.c
+++ b/tests/json-loader.c
@@ -24,6 +24,18 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
static GVariant * node2variant (JsonNode * node, const gchar * name);
static void
+array_byte_foreach (JsonArray * array, guint index, JsonNode * node, gpointer user_data)
+{
+ g_return_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_VALUE);
+ g_return_if_fail(json_node_get_value_type(node) == G_TYPE_INT || json_node_get_value_type(node) == G_TYPE_INT64);
+
+ GVariantBuilder * builder = (GVariantBuilder *)user_data;
+
+ g_variant_builder_add_value(builder, g_variant_new_byte(json_node_get_int(node)));
+ return;
+}
+
+static void
array_foreach (JsonArray * array, guint index, JsonNode * node, gpointer user_data)
{
GVariantBuilder * builder = (GVariantBuilder *)user_data;
@@ -79,11 +91,17 @@ node2variant (JsonNode * node, const gchar * name)
}
if (JSON_NODE_TYPE(node) == JSON_NODE_ARRAY) {
+ JsonArray * array = json_node_get_array(node);
GVariantBuilder builder;
- g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
- JsonArray * array = json_node_get_array(node);
- json_array_foreach_element(array, array_foreach, &builder);
+ if (g_strcmp0(name, "icon-data") == 0) {
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("ay"));
+ json_array_foreach_element(array, array_byte_foreach, &builder);
+ } else {
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+ json_array_foreach_element(array, array_foreach, &builder);
+ }
+
return g_variant_builder_end(&builder);
}
diff --git a/tests/test-json-client.c b/tests/test-json-client.c
index d4e782b..8900902 100644
--- a/tests/test-json-client.c
+++ b/tests/test-json-client.c
@@ -27,14 +27,6 @@ GMainLoop * mainloop = NULL;
gboolean
timeout_func (gpointer user_data)
{
- g_warning("Timeout without getting name");
- g_main_loop_quit(mainloop);
- return FALSE;
-}
-
-void
-name_appeared (GDBusConnection * connection, const gchar * name, const gchar * owner, gpointer user_data)
-{
char ** argv = (char **)user_data;
g_usleep(500000);
@@ -52,25 +44,18 @@ name_appeared (GDBusConnection * connection, const gchar * name, const gchar * o
g_file_replace_contents(ofile, output, g_utf8_strlen(output, -1), NULL, FALSE, 0, NULL, NULL, NULL);
}
+ g_spawn_command_line_sync("gdbus call --session --dest org.dbusmenu.test --object-path /org/test --method com.canonical.dbusmenu.Event 0 clicked \"<0>\" 0", NULL, NULL, NULL, NULL);
+
g_main_loop_quit(mainloop);
- return;
+ return TRUE;
}
int
main (int argc, char ** argv)
{
g_type_init();
- g_debug("Wait for friends");
-
- g_bus_watch_name(G_BUS_TYPE_SESSION,
- "org.dbusmenu.test",
- G_BUS_NAME_WATCHER_FLAGS_NONE,
- name_appeared,
- NULL,
- argv,
- NULL);
- g_timeout_add_seconds(2, timeout_func, NULL);
+ g_timeout_add_seconds(1, timeout_func, argv);
mainloop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(mainloop);
diff --git a/tests/test-json-instruction-count b/tests/test-json-instruction-count
new file mode 100755
index 0000000..3a4db97
--- /dev/null
+++ b/tests/test-json-instruction-count
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+COMMAND=$@
+INSTRUCTIONS=`valgrind --tool=callgrind --callgrind-out-file=/dev/null --instr-atstart=no --collect-atstart=no --combine-dumps=yes $COMMAND 2>&1 > /dev/null | grep refs | grep I | tail --lines=1 | cut -d ":" -f 2 | sed -e 's/^[ \t]*//'`
+
+echo "Instructions needed to execute '$COMMAND': $INSTRUCTIONS"
diff --git a/tests/test-json-server.c b/tests/test-json-server.c
index 083de60..7165838 100644
--- a/tests/test-json-server.c
+++ b/tests/test-json-server.c
@@ -22,6 +22,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib.h>
#include <gio/gio.h>
+#include "callgrind.h"
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/menuitem.h>
@@ -29,11 +30,14 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
static GMainLoop * mainloop = NULL;
-static gboolean
-timer_func (gpointer data)
+static void
+root_activate (void)
{
+ g_debug("Dumping callgrind data");
+ CALLGRIND_DUMP_STATS_AT("exported");
+ CALLGRIND_STOP_INSTRUMENTATION;
g_main_loop_quit(mainloop);
- return FALSE;
+ return;
}
static void
@@ -50,9 +54,13 @@ on_bus (GDBusConnection * connection, const gchar * name, gpointer user_data)
return;
}
- dbusmenu_server_set_root(server, root);
+ g_signal_connect(G_OBJECT(root), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(root_activate), NULL);
- g_timeout_add(10000, timer_func, NULL);
+ g_debug("Starting Callgrind");
+ CALLGRIND_START_INSTRUMENTATION;
+ CALLGRIND_ZERO_STATS;
+ CALLGRIND_TOGGLE_COLLECT;
+ dbusmenu_server_set_root(server, root);
return;
}
diff --git a/tools/dbusmenu-dumper.c b/tools/dbusmenu-dumper.c
index 2db437d..6dcdb2f 100644
--- a/tools/dbusmenu-dumper.c
+++ b/tools/dbusmenu-dumper.c
@@ -28,6 +28,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libdbusmenu-glib/client.h>
#include <libdbusmenu-glib/menuitem.h>
+#include <libdbusmenu-glib/menuitem-private.h>
#include <X11/Xlib.h>
@@ -77,6 +78,7 @@ print_menuitem (DbusmenuMenuitem * item, int depth)
return;
}
+/* Prints the final JSON file recursively */
static gboolean
root_timeout (gpointer data)
{
@@ -90,6 +92,51 @@ root_timeout (gpointer data)
return FALSE;
}
+/* Variables to deal with the number of items that we're watching to
+ realized */
+static int realized_count = 0;
+static DbusmenuMenuitem * root = NULL;
+
+/* Decrements the realization count, and if it gets to the end prints
+ out everything. */
+static void
+decrement_count (void)
+{
+ realized_count--;
+
+ if (realized_count == 0) {
+ root_timeout(root);
+ }
+
+ return;
+}
+
+/* Checks whether we need to watch a menu item, and recurses down to
+ it's children as well */
+static void
+check_realizations (DbusmenuMenuitem * item)
+{
+ g_return_if_fail(DBUSMENU_IS_MENUITEM(item));
+
+ if (!dbusmenu_menuitem_realized(item)) {
+ realized_count++;
+
+ g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_REALIZED, G_CALLBACK(decrement_count), NULL);
+ }
+
+ GList * children = dbusmenu_menuitem_get_children(item);
+ if (children != NULL) {
+ GList * child;
+ for (child = children; child != NULL; child = g_list_next(child)) {
+ check_realizations(DBUSMENU_MENUITEM(child->data));
+ }
+ }
+
+ return;
+}
+
+/* A setup for when we get our first root. We set up the basic realization
+ counter and set it to run. We'll print when it counts down */
static void
new_root_cb (DbusmenuClient * client, DbusmenuMenuitem * newroot)
{
@@ -99,7 +146,12 @@ new_root_cb (DbusmenuClient * client, DbusmenuMenuitem * newroot)
return;
}
- g_timeout_add_seconds(2, root_timeout, newroot);
+ root = newroot;
+ check_realizations(root);
+
+ realized_count++;
+ decrement_count();
+
return;
}