← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~ted/dbusmenu/errr-reordering into lp:dbusmenu

 

Ted Gould has proposed merging lp:~ted/dbusmenu/errr-reordering into lp:dbusmenu.

    Requested reviews:
    DBus Menu Team (dbusmenu-team)


Fixes reordering by adding a case in the new item where we notice that it's already been realized.  Also, fixes some other problems by removing the item frome the menu when it's deleted as child.  This is kinda how the parse works, not ideal really, but this gets rid of those bugs.

There is also a lot of debugging information that is signaled with --enable-massivedebugging.  That was required to track down these problems, and will probably be required in the future as well.
-- 
https://code.launchpad.net/~ted/dbusmenu/errr-reordering/+merge/12803
Your team ayatana-commits is subscribed to branch lp:dbusmenu.
=== modified file '.bzrignore'
--- .bzrignore	2009-09-02 18:29:01 +0000
+++ .bzrignore	2009-10-02 20:15:20 +0000
@@ -42,3 +42,9 @@
 mago.results
 test-glib-simple-items
 libdbusmenu-gtk/libdbusmenu_gtk_la-menuitem.lo
+tests/test-glib-layout
+tests/test-glib-properties
+tests/test-gtk-label
+tests/test-gtk-reorder-server.c
+tests/test-gtk-reorder-server
+tests/test-gtk-reorder

=== modified file 'configure.ac'
--- configure.ac	2009-09-24 21:07:24 +0000
+++ configure.ac	2009-10-02 20:15:20 +0000
@@ -84,6 +84,16 @@
 AM_GLIB_GNU_GETTEXT
 
 ###########################
+# Massive Debugging
+###########################
+
+with_massivedebugging="no"
+AC_ARG_ENABLE(massivedebugging, AS_HELP_STRING([--enable-massivedebugging], [Print out so much information your brain will hurt]), with_massivedebugging=$enableval, with_massivedebugging=no)
+if test "x$with_massivedebugging" = "xyes"; then
+	AC_DEFINE([MASSIVEDEBUGGING], [1], [Print everyting])
+fi
+
+###########################
 # Files
 ###########################
 
@@ -109,5 +119,6 @@
 libdbusmenu Configuration:
 
 	Prefix:                 $prefix
+	Massive Debugging:      $with_massivedebugging
 ])
 

=== modified file 'libdbusmenu-glib/client.c'
--- libdbusmenu-glib/client.c	2009-10-02 13:52:39 +0000
+++ libdbusmenu-glib/client.c	2009-10-02 20:15:20 +0000
@@ -322,6 +322,10 @@
 static void
 id_prop_update (DBusGProxy * proxy, guint id, gchar * property, gchar * value, DbusmenuClient * client)
 {
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Property change sent to client for item %d property %s value %s", id, property, g_utf8_strlen(value, 50) < 25 ? value : "<too long>");
+	#endif
+
 	DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
 	g_return_if_fail(priv->root != NULL);
 
@@ -337,6 +341,10 @@
 static void
 id_update (DBusGProxy * proxy, guint id, DbusmenuClient * client)
 {
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Client side ID update: %d", id);
+	#endif 
+
 	DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
 	g_return_if_fail(priv->root != NULL);
 
@@ -414,6 +422,9 @@
 	if (priv->root != NULL) {
 		g_object_unref(G_OBJECT(priv->root));
 		priv->root = NULL;
+		#ifdef MASSIVEDEBUGGING
+		g_debug("Proxies destroyed, signaling a root change and a layout update.");
+		#endif
 		g_signal_emit(G_OBJECT(userdata), signals[ROOT_CHANGED], 0, NULL, TRUE);
 		g_signal_emit(G_OBJECT(userdata), signals[LAYOUT_UPDATED], 0, TRUE);
 	}
@@ -606,6 +617,9 @@
 		handled = newfunc(propdata->item, propdata->parent, propdata->client);
 	}
 
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Client has realized a menuitem: %d", dbusmenu_menuitem_get_id(propdata->item));
+	#endif
 	g_signal_emit(G_OBJECT(propdata->item), DBUSMENU_MENUITEM_SIGNAL_REALIZED_ID, 0, TRUE);
 
 	if (!handled) {
@@ -643,7 +657,9 @@
 parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy)
 {
 	guint id = parse_node_get_id(node);
-	/* g_debug("Looking at node with id: %d", id); */
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Client looking at node with id: %d", id);
+	#endif
 	if (item == NULL || dbusmenu_menuitem_get_id(item) != id || id == 0) {
 		if (item != NULL) {
 			if (parent != NULL) {
@@ -707,7 +723,9 @@
 	GList * oldchildleft = NULL;
 	for (oldchildleft = oldchildren; oldchildleft != NULL; oldchildleft = g_list_next(oldchildleft)) {
 		DbusmenuMenuitem * oldmi = DBUSMENU_MENUITEM(oldchildleft->data);
+		#ifdef MASSIVEDEBUGGING
 		g_debug("Unref'ing menu item with layout update. ID: %d", dbusmenu_menuitem_get_id(oldmi));
+		#endif
 		g_object_unref(G_OBJECT(oldmi));
 	}
 	g_list_free(oldchildren);
@@ -720,6 +738,10 @@
 static gint
 parse_layout (DbusmenuClient * client, const gchar * layout)
 {
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Client Parsing a new layout");
+	#endif 
+
 	DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
 
 	xmlDocPtr xmldoc;
@@ -738,6 +760,9 @@
 	}
 
 	if (priv->root != oldroot) {
+		#ifdef MASSIVEDEBUGGING
+		g_debug("Client signaling root changed.");
+		#endif 
 		g_signal_emit(G_OBJECT(client), signals[ROOT_CHANGED], 0, priv->root, TRUE);
 	}
 
@@ -772,6 +797,9 @@
 
 	priv->my_revision = rev;
 	/* g_debug("Root is now: 0x%X", (unsigned int)priv->root); */
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Client signaling layout has changed.");
+	#endif 
 	g_signal_emit(G_OBJECT(client), signals[LAYOUT_UPDATED], 0, TRUE);
 
 	if (priv->my_revision < priv->current_revision) {
@@ -860,6 +888,10 @@
 		return NULL;
 	}
 
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Client get root: %X", (guint)priv->root);
+	#endif
+
 	return priv->root;
 }
 
@@ -892,6 +924,10 @@
 
 	DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
 
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Adding a type handler for '%s'", type);
+	#endif
+
 	if (priv->type_handlers == NULL) {
 		g_warning("Type handlers hashtable not built");
 		return FALSE;

=== modified file 'libdbusmenu-glib/menuitem.c'
--- libdbusmenu-glib/menuitem.c	2009-09-21 20:01:40 +0000
+++ libdbusmenu-glib/menuitem.c	2009-10-02 20:15:20 +0000
@@ -32,6 +32,11 @@
 #include "menuitem.h"
 #include "menuitem-marshal.h"
 
+#ifdef MASSIVEDEBUGGING
+#define LABEL(x)  dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(x), DBUSMENU_MENUITEM_PROP_LABEL)
+#define ID(x)     dbusmenu_menuitem_get_id(DBUSMENU_MENUITEM(x))
+#endif
+
 /* Private */
 /**
 	DbusmenuMenuitemPrivate:
@@ -362,6 +367,9 @@
 static void
 take_children_signal (gpointer data, gpointer user_data)
 {
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Menuitem %d (%s) signalling child removed %d (%s)", ID(user_data), LABEL(user_data), ID(data), LABEL(data));
+	#endif
 	g_signal_emit(G_OBJECT(user_data), signals[CHILD_REMOVED], 0, DBUSMENU_MENUITEM(data), TRUE);
 	return;
 }
@@ -404,6 +412,11 @@
 guint
 dbusmenu_menuitem_get_position (DbusmenuMenuitem * mi, DbusmenuMenuitem * parent)
 {
+	#ifdef MASSIVEDEBUGGING
+	if (!DBUSMENU_IS_MENUITEM(mi))     g_warning("Getting position of %d (%s), it's at: %d (mi fail)", ID(mi), LABEL(mi), 0);
+	if (!DBUSMENU_IS_MENUITEM(parent)) g_warning("Getting position of %d (%s), it's at: %d (parent fail)", ID(mi), LABEL(mi), 0);
+	#endif
+
 	/* TODO: I'm not too happy returning zeros here.  But that's all I've got */
 	g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), 0);
 	g_return_val_if_fail(DBUSMENU_IS_MENUITEM(parent), 0);
@@ -417,6 +430,10 @@
 
 	if (childs == NULL) return 0;
 
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Getting position of %d (%s), it's at: %d", ID(mi), LABEL(mi), count);
+	#endif
+
 	return count;
 }
 
@@ -438,6 +455,9 @@
 
 	DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
 	priv->children = g_list_append(priv->children, child);
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Menuitem %d (%s) signalling child added %d (%s) at %d", ID(mi), LABEL(mi), ID(child), LABEL(child), g_list_length(priv->children) - 1);
+	#endif
 	g_signal_emit(G_OBJECT(mi), signals[CHILD_ADDED], 0, child, g_list_length(priv->children) - 1, TRUE);
 	return TRUE;
 }
@@ -460,6 +480,9 @@
 
 	DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
 	priv->children = g_list_prepend(priv->children, child);
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Menuitem %d (%s) signalling child added %d (%s) at %d", ID(mi), LABEL(mi), ID(child), LABEL(child), 0);
+	#endif
 	g_signal_emit(G_OBJECT(mi), signals[CHILD_ADDED], 0, child, 0, TRUE);
 	return TRUE;
 }
@@ -483,6 +506,9 @@
 
 	DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
 	priv->children = g_list_remove(priv->children, child);
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Menuitem %d (%s) signalling child removed %d (%s)", ID(mi), LABEL(mi), ID(child), LABEL(child));
+	#endif
 	g_signal_emit(G_OBJECT(mi), signals[CHILD_REMOVED], 0, child, TRUE);
 	return TRUE;
 }
@@ -507,6 +533,9 @@
 
 	DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
 	priv->children = g_list_insert(priv->children, child, position);
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Menuitem %d (%s) signalling child added %d (%s) at %d", ID(mi), LABEL(mi), ID(child), LABEL(child), position);
+	#endif
 	g_signal_emit(G_OBJECT(mi), signals[CHILD_ADDED], 0, child, position, TRUE);
 	return TRUE;
 }
@@ -543,6 +572,9 @@
 	priv->children = g_list_remove(priv->children, child);
 	priv->children = g_list_insert(priv->children, child, position);
 
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Menuitem %d (%s) signalling child %d (%s) moved from %d to %d", ID(mi), LABEL(mi), ID(child), LABEL(child), oldpos, position);
+	#endif
 	g_signal_emit(G_OBJECT(mi), signals[CHILD_MOVED], 0, child, position, oldpos, TRUE);
 
 	return TRUE;
@@ -658,6 +690,9 @@
 	gchar * lval = g_strdup(value);
 
 	g_hash_table_insert(priv->properties, lprop, lval);
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Menuitem %d (%s) signalling property '%s' changed to '%s'", ID(mi), LABEL(mi), property, g_utf8_strlen(value, 50) < 25 ? value : "<too long>");
+	#endif
 	g_signal_emit(G_OBJECT(mi), signals[PROPERTY_CHANGED], 0, property, value, TRUE);
 
 	return TRUE;
@@ -882,6 +917,9 @@
 dbusmenu_menuitem_activate (DbusmenuMenuitem * mi)
 {
 	g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));
+	#ifdef MASSIVEDEBUGGING
+	g_debug("Menuitem %d (%s) activated", ID(mi), LABEL(mi));
+	#endif
 	g_signal_emit(G_OBJECT(mi), signals[ITEM_ACTIVATED], 0, TRUE);
 	return;
 }

=== modified file 'libdbusmenu-gtk/Makefile.am'
--- libdbusmenu-gtk/Makefile.am	2009-09-02 18:29:01 +0000
+++ libdbusmenu-gtk/Makefile.am	2009-10-02 20:15:20 +0000
@@ -26,7 +26,7 @@
 	-export-symbols-regex "^[^_].*"
 
 libdbusmenu_gtk_la_CFLAGS = \
-	$(DBUSMENUGTK_CFLAGS) -I$(srcdir)/.. -Wall -Werror
+	$(DBUSMENUGTK_CFLAGS) -I$(srcdir)/.. -Wall -Werror -DG_DISABLE_DEPRECATED -DG_LOG_DOMAIN="\"LIBDBUSMENU-GTK\""
 
 libdbusmenu_gtk_la_LIBADD = \
 	../libdbusmenu-glib/libdbusmenu-glib.la \

=== modified file 'libdbusmenu-gtk/client.c'
--- libdbusmenu-gtk/client.c	2009-09-09 21:50:48 +0000
+++ libdbusmenu-gtk/client.c	2009-10-02 20:15:20 +0000
@@ -159,7 +159,9 @@
 static void
 destoryed_dbusmenuitem_cb (gpointer udata, GObject * dbusmenuitem)
 {
-	/* g_debug("DbusmenuMenuitem was destroyed"); */
+	#ifdef MASSIVEDEBUGGING
+	g_debug("DbusmenuMenuitem was destroyed");
+	#endif
 	gtk_widget_destroy(GTK_WIDGET(udata));
 	return;
 }
@@ -176,6 +178,15 @@
 	return;
 }
 
+#ifdef MASSIVEDEBUGGING
+static void
+destroy_gmi (GtkMenuItem * gmi, DbusmenuMenuitem * mi)
+{
+	g_debug("Destorying GTK Menuitem for %d", dbusmenu_menuitem_get_id(mi));
+	return;
+}
+#endif
+
 /**
 	dbusmenu_gtkclient_newitem_base:
 	@client: The client handling everything on this connection
@@ -195,8 +206,16 @@
 void
 dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem * item, GtkMenuItem * gmi, DbusmenuMenuitem * parent)
 {
+	#ifdef MASSIVEDEBUGGING
+	g_debug("GTK Client new item base for %d", dbusmenu_menuitem_get_id(item));
+	#endif
+
 	/* Attach these two */
 	g_object_set_data(G_OBJECT(item), data_menuitem, gmi);
+	g_object_ref(G_OBJECT(gmi));
+	#ifdef MASSIVEDEBUGGING
+	g_signal_connect(G_OBJECT(gmi), "destroy", G_CALLBACK(destroy_gmi), item);
+	#endif
 
 	/* DbusmenuMenuitem signals */
 	g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_change_cb), gmi);
@@ -222,6 +241,10 @@
 static void
 new_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint position, DbusmenuGtkClient * gtkclient)
 {
+	#ifdef MASSIVEDEBUGGING
+	g_debug("GTK Client new child for %d on %d at %d", dbusmenu_menuitem_get_id(mi), dbusmenu_menuitem_get_id(child), position);
+	#endif
+
 	if (dbusmenu_menuitem_get_root(mi)) { return; }
 
 	gpointer ann_menu = g_object_get_data(G_OBJECT(mi), data_menu);
@@ -316,14 +339,13 @@
 	g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), NULL);
 	g_return_val_if_fail(DBUSMENU_IS_MENUITEM(item), NULL);
 
-	GtkMenuItem * mi = GTK_MENU_ITEM(g_object_get_data(G_OBJECT(item), data_menuitem));
-	if (mi == NULL) {
-		// new_menuitem(DBUSMENU_CLIENT(client), item, NULL);
+	gpointer data = g_object_get_data(G_OBJECT(item), data_menuitem);
+	if (data == NULL) {
 		g_warning("GTK not updated");
-		mi = GTK_MENU_ITEM(g_object_get_data(G_OBJECT(item), data_menuitem));
+		return NULL;
 	}
 
-	return mi;
+	return GTK_MENU_ITEM(data);
 }
 
 /* The base type handler that builds a plain ol'

=== modified file 'libdbusmenu-gtk/menu.c'
--- libdbusmenu-gtk/menu.c	2009-09-09 22:09:10 +0000
+++ libdbusmenu-gtk/menu.c	2009-10-02 20:15:20 +0000
@@ -185,6 +185,28 @@
 
 /* Internal Functions */
 
+#ifdef MASSIVEDEBUGGING
+typedef struct {
+	GtkMenuItem * mi;
+	gint finalpos;
+	gboolean found;
+} menu_pos_t;
+
+static void
+find_pos (GtkWidget * widget, gpointer data)
+{
+	menu_pos_t * menu_pos = (menu_pos_t *)data;
+	if (menu_pos->found) return;
+	if ((gpointer)(menu_pos->mi) == (gpointer)widget) {
+		menu_pos->found = TRUE;
+	} else {
+		menu_pos->finalpos++;
+	}
+	return;
+}
+#endif
+
+
 /* Called when a new child of the root item is
    added.  Sets up a signal for when it's actually
    realized. */
@@ -192,7 +214,24 @@
 root_child_added (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint position, DbusmenuGtkMenu * menu)
 {
 	g_debug("Root new child");
+	DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu);
+
 	g_signal_connect(G_OBJECT(child), DBUSMENU_MENUITEM_SIGNAL_REALIZED, G_CALLBACK(child_realized), menu);
+
+	GtkMenuItem * mi = dbusmenu_gtkclient_menuitem_get(priv->client, child);
+	if (mi != NULL) {
+		GtkWidget * item = GTK_WIDGET(mi);
+		gtk_menu_insert(GTK_MENU(menu), item, position);
+		#ifdef MASSIVEDEBUGGING
+		menu_pos_t menu_pos;
+		menu_pos.mi = mi;
+		menu_pos.finalpos = 0;
+		menu_pos.found = FALSE;
+
+		gtk_container_foreach(GTK_CONTAINER(menu), find_pos, &menu_pos);
+		g_debug("Menu position requested was %d but got %d", position, menu_pos.finalpos);
+		#endif
+	}
 	return;
 }
 
@@ -212,6 +251,12 @@
 root_child_delete (DbusmenuMenuitem * root, DbusmenuMenuitem * child, DbusmenuGtkMenu * menu)
 {
 	g_debug("Root child deleted");
+	DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu);
+	GtkWidget * item = GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child));
+	if (item != NULL) {
+		gtk_container_remove(GTK_CONTAINER(menu), item);
+	}
+
 	if (g_list_length(dbusmenu_menuitem_get_children(root)) == 0) {
 		gtk_widget_hide(GTK_WIDGET(menu));
 	}
@@ -223,6 +268,7 @@
 static void
 child_realized (DbusmenuMenuitem * child, gpointer userdata)
 {
+	g_debug("Root child realized");
 	g_return_if_fail(DBUSMENU_IS_GTKMENU(userdata));
 
 	DbusmenuGtkMenu * menu = DBUSMENU_GTKMENU(userdata);

=== modified file 'tests/Makefile.am'
--- tests/Makefile.am	2009-07-01 05:34:05 +0000
+++ tests/Makefile.am	2009-10-02 20:15:20 +0000
@@ -1,12 +1,15 @@
 SUBDIRS = dbusmenu-gtk
 
-check: tests
-
 DBUS_RUNNER=dbus-test-runner --dbus-config /usr/share/dbus-test-runner/session.conf
 
-tests: test-glib-layout test-glib-properties test-gtk-label test-glib-simple-items
+TESTS = \
+	test-glib-layout \
+	test-glib-properties \
+	test-gtk-label \
+	test-glib-simple-items \
+	test-gtk-reorder
 
-libexec_PROGRAMS = \
+check_PROGRAMS = \
 	glib-server-nomenu \
 	test-glib-layout-client \
 	test-glib-layout-server \
@@ -14,7 +17,8 @@
 	test-glib-properties-server \
 	test-gtk-label-client \
 	test-gtk-label-server \
-	test-glib-simple-items
+	test-glib-simple-items \
+	test-gtk-reorder-server
 
 glib_server_nomenu_SOURCES = \
 	glib-server-nomenu.c
@@ -27,10 +31,14 @@
 	../libdbusmenu-glib/libdbusmenu-glib.la \
 	$(DBUSMENUGLIB_LIBS)
 
-
+######################
+# Test Glib Layout
+######################
 
 test-glib-layout: test-glib-layout-client test-glib-layout-server
-	$(DBUS_RUNNER) --task ./test-glib-layout-client --task-name Client --task ./test-glib-layout-server --task-name Server --ignore-return
+	@echo "#!/bin/sh" > test-glib-layout
+	@echo $(DBUS_RUNNER) --task ./test-glib-layout-client --task-name Client --task ./test-glib-layout-server --task-name Server --ignore-return >> test-glib-layout
+	@chmod +x test-glib-layout
 
 test_glib_layout_server_SOURCES = \
 	test-glib-layout.h \
@@ -57,9 +65,14 @@
 	$(DBUSMENUGLIB_LIBS)
 
 
+######################
+# Test Glib Properties
+######################
 
 test-glib-properties: test-glib-properties-client test-glib-properties-server
-	$(DBUS_RUNNER) --task ./test-glib-properties-client --task-name Client --task ./test-glib-properties-server --task-name Server --ignore-return
+	@echo "#!/bin/sh" > test-glib-properties
+	@echo $(DBUS_RUNNER) --task ./test-glib-properties-client --task-name Client --task ./test-glib-properties-server --task-name Server --ignore-return >> test-glib-properties
+	@chmod +x test-glib-properties
 
 test_glib_properties_server_SOURCES = \
 	test-glib-properties.h \
@@ -85,6 +98,9 @@
 	../libdbusmenu-glib/libdbusmenu-glib.la \
 	$(DBUSMENUGLIB_LIBS)
 
+#########################
+# Test Glib Simple Items
+#########################
 
 test_glib_simple_items_SOURCES = \
 	test-glib-simple-items.c
@@ -97,9 +113,14 @@
 	../libdbusmenu-glib/libdbusmenu-glib.la \
 	$(DBUSMENUGLIB_LIBS)
 
+#########################
+# Test GTK Label
+#########################
 
 test-gtk-label: test-gtk-label-client test-gtk-label-server test-gtk-label.json
-	$(DBUS_RUNNER) --task ./test-gtk-label-client --task-name Client --task ./test-gtk-label-server --parameter $(srcdir)/test-gtk-label.json --task-name Server --ignore-return
+	@echo "#!/bin/sh" > test-gtk-label
+	@echo $(DBUS_RUNNER) --task ./test-gtk-label-client --task-name Client --task ./test-gtk-label-server --parameter $(srcdir)/test-gtk-label.json --task-name Server --ignore-return >> test-gtk-label
+	@chmod +x test-gtk-label
 
 test_gtk_label_server_SOURCES = \
 	test-gtk-label-server.c
@@ -131,7 +152,34 @@
 	$(DBUSMENUGTK_LIBS) \
 	$(DBUSMENUTESTS_LIBS)
 
-
+#########################
+# Test GTK Reorder
+#########################
+
+test-gtk-reorder: test-gtk-label-client test-gtk-reorder-server
+	@echo "#!/bin/sh" > test-gtk-reorder
+	@echo $(DBUS_RUNNER) --task ./test-gtk-label-client --task-name Client --task ./test-gtk-reorder-server --parameter $(srcdir)/test-gtk-label.json --task-name Server --ignore-return >> test-gtk-reorder
+	@chmod +x test-gtk-reorder
+
+test_gtk_reorder_server_SOURCES = \
+	test-gtk-reorder-server.c
+
+test_gtk_reorder_server_CFLAGS = \
+	-I $(srcdir)/.. \
+	$(DBUSMENUGTK_CFLAGS) \
+	$(DBUSMENUTESTS_CFLAGS) \
+	$(DBUSMENUGLIB_CFLAGS) -Wall -Werror
+
+test_gtk_reorder_server_LDADD = \
+	../libdbusmenu-glib/libdbusmenu-glib.la \
+	../libdbusmenu-gtk/libdbusmenu-gtk.la \
+	$(DBUSMENUGTK_LIBS) \
+	$(DBUSMENUTESTS_LIBS)
+
+
+#########################
+# Other
+#########################
 
 examplesdir = $(docdir)/examples/
 

=== modified file 'tests/test-glib-simple-items.c'
--- tests/test-glib-simple-items.c	2009-07-01 05:34:05 +0000
+++ tests/test-glib-simple-items.c	2009-10-02 20:15:20 +0000
@@ -25,6 +25,13 @@
 	return;
 }
 
+static gboolean
+quititall (gpointer data)
+{
+	g_main_quit(mainloop);
+	return FALSE;
+}
+
 int
 main (int argc, char ** argv)
 {
@@ -37,6 +44,8 @@
 
 	dummy_users(root_menuitem);
 
+	g_timeout_add_seconds(1, quititall, NULL);
+
     mainloop = g_main_loop_new(NULL, FALSE);
     g_main_loop_run(mainloop);
 

=== added file 'tests/test-gtk-reorder-server.c'
--- tests/test-gtk-reorder-server.c	1970-01-01 00:00:00 +0000
+++ tests/test-gtk-reorder-server.c	2009-10-02 20:15:20 +0000
@@ -0,0 +1,119 @@
+/*
+A test for libdbusmenu to ensure its quality.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+    Ted Gould <ted@xxxxxxxxxxxxx>
+
+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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus-glib-bindings.h>
+
+#include <libdbusmenu-glib/menuitem.h>
+#include <libdbusmenu-glib/server.h>
+
+#define NUMBER_TESTS    5
+#define NUMBER_ENTRIES  5
+
+guint ordering [NUMBER_TESTS][NUMBER_ENTRIES] = {
+	{0, 1, 2, 3, 4},
+	{1, 2, 3, 4, 0},
+	{3, 1, 4, 2, 0},
+	{4, 3, 2, 1, 0},
+	{0, 1, 2, 3, 4}
+};
+
+gchar * names [NUMBER_ENTRIES] = {
+	"One", "Two", "Three", "Four", "Five"
+};
+
+DbusmenuMenuitem * entries[NUMBER_ENTRIES] = {0};
+DbusmenuMenuitem * root = NULL;
+
+gint test = 0;
+
+static DbusmenuServer * server = NULL;
+static GMainLoop * mainloop = NULL;
+
+static gboolean
+timer_func (gpointer data)
+{
+	if (test == NUMBER_TESTS) {
+		g_main_quit(mainloop);
+		return FALSE;
+	}
+
+	g_debug("Testing pattern %d", test);
+
+	int i;
+	for (i = 0; i < NUMBER_ENTRIES; i++) {
+		g_debug("Putting entry '%d' at position '%d'", i, ordering[test][i]);
+		dbusmenu_menuitem_child_reorder(root, entries[i], ordering[test][i]);
+		dbusmenu_menuitem_property_set(entries[i], "label", names[i]);
+	}
+
+	test++;
+	return TRUE;
+}
+
+int
+main (int argc, char ** argv)
+{
+	GError * error = NULL;
+
+	g_type_init();
+
+	DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+	g_debug("DBus ID: %s", dbus_connection_get_server_id(dbus_g_connection_get_connection(dbus_g_bus_get(DBUS_BUS_SESSION, NULL))));
+
+	DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+	guint nameret = 0;
+
+	if (!org_freedesktop_DBus_request_name(bus_proxy, "glib.label.test", 0, &nameret, &error)) {
+		g_error("Unable to call to request name");
+		return 1;
+	}
+
+	if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+		g_error("Unable to get name");
+		return 1;
+	}
+
+	server = dbusmenu_server_new("/org/test");
+	root = dbusmenu_menuitem_new();
+	dbusmenu_server_set_root(server, root);
+
+	int i;
+	for (i = 0; i < NUMBER_ENTRIES; i++) {
+		entries[i] = dbusmenu_menuitem_new();
+		dbusmenu_menuitem_child_append(root, entries[i]);
+	}
+
+	timer_func(NULL);
+	g_timeout_add_seconds(5, timer_func, NULL);
+
+	mainloop = g_main_loop_new(NULL, FALSE);
+	g_main_loop_run(mainloop);
+
+	g_debug("Quiting");
+
+	return 0;
+}
+


Follow ups