← Back to team overview

ayatana-commits team mailing list archive

[Merge] lp:~ted/appmenu-gtk/dbusmenu-parser into lp:appmenu-gtk

 

Ted Gould has proposed merging lp:~ted/appmenu-gtk/dbusmenu-parser into lp:appmenu-gtk with lp:~mterry/appmenu-gtk/misc-fixes as a prerequisite.

Requested reviews:
  Canonical Desktop Experience Team (canonical-dx-team)

For more details, see:
https://code.launchpad.net/~ted/appmenu-gtk/dbusmenu-parser/+merge/47623

Switch to using the dbusmenu parser for parsing menu items.
-- 
https://code.launchpad.net/~ted/appmenu-gtk/dbusmenu-parser/+merge/47623
Your team ayatana-commits is subscribed to branch lp:appmenu-gtk.
=== modified file 'src/bridge.c'
--- src/bridge.c	2011-01-27 02:01:27 +0000
+++ src/bridge.c	2011-01-27 02:01:27 +0000
@@ -28,6 +28,7 @@
 #include <gio/gio.h>
 
 #include <libdbusmenu-gtk/menuitem.h>
+#include <libdbusmenu-gtk/parser.h>
 #include <libdbusmenu-glib/menuitem.h>
 #include <libdbusmenu-glib/server.h>
 
@@ -65,7 +66,6 @@
 {
   GtkWidget        *window;
   DbusmenuServer   *server;
-  DbusmenuMenuitem *root;
   gchar            *path;
   gboolean          registered;
   AppMenuBridge    *bridge;
@@ -171,12 +171,6 @@
       context->path = NULL;
     }
 
-  if (context->root != NULL)
-    {
-      g_object_unref (context->root);
-      context->root = NULL;
-    }
-
   if (context->server != NULL)
     {
       g_object_unref (context->server);
@@ -335,7 +329,7 @@
             }
         }
 
-      if (!context->registered && context->server != NULL && context->root != NULL && GTK_IS_WINDOW (widget) && bridge->priv->appmenuproxy != NULL)
+      if (!context->registered && context->server != NULL && GTK_IS_WINDOW (widget) && bridge->priv->appmenuproxy != NULL)
         {
           g_dbus_proxy_call(bridge->priv->appmenuproxy,
                             "RegisterWindow",
@@ -443,584 +437,6 @@
 	return;
 }
 
-
-static GtkWidget *
-find_menu_label (GtkWidget *widget)
-{
-  GtkWidget *label = NULL;
-
-  if (GTK_IS_LABEL (widget))
-    return widget;
-
-  if (GTK_IS_CONTAINER (widget))
-    {
-      GList *children;
-      GList *l;
-
-      children = gtk_container_get_children (GTK_CONTAINER (widget));
-
-      for (l = children; l; l = l->next)
-        {
-          label = find_menu_label (l->data);
-
-          if (label)
-            break;
-        }
-
-      g_list_free (children);
-    }
-
-  return label;
-}
-
-static void
-item_activated (DbusmenuMenuitem *item, guint timestamp, gpointer user_data)
-{
-  GtkWidget *child;
-
-  if (user_data != NULL)
-    {
-      child = (GtkWidget *)user_data;
-
-      if (GTK_IS_MENU_ITEM (child))
-        {
-          gtk_menu_item_activate (GTK_MENU_ITEM (child));
-        }
-    }
-}
-
-static gboolean
-item_about_to_show (DbusmenuMenuitem *item, gpointer user_data)
-{
-  GtkWidget *child;
-
-  if (user_data != NULL)
-    {
-      child = (GtkWidget *)user_data;
-
-      if (GTK_IS_MENU_ITEM (child))
-        {
-          // Only called for items with submens.  So we activate it here in
-          // case the program dynamically creates menus (like empathy does)
-          gtk_menu_item_activate (GTK_MENU_ITEM (child));
-        }
-    }
-
-  return TRUE;
-}
-
-static gboolean
-should_show_image (GtkImage *image)
-{
-  GtkWidget *item;
-
-  item = gtk_widget_get_ancestor (GTK_WIDGET (image),
-                                  GTK_TYPE_IMAGE_MENU_ITEM);
-
-  if (item)
-    {
-      GtkSettings *settings;
-      gboolean gtk_menu_images;
-
-      settings = gtk_widget_get_settings (item);
-
-      g_object_get (settings, "gtk-menu-images", &gtk_menu_images, NULL);
-
-      if (gtk_menu_images)
-        return TRUE;
-
-      return gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item));
-    }
-
-  return FALSE;
-}
-
-static gboolean
-update_stock_item (DbusmenuMenuitem *menuitem,
-                   GtkWidget        *widget)
-{
-  GtkStockItem stock;
-  GtkImage *image;
-
-  g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
-
-  image = GTK_IMAGE (widget);
-
-  if (gtk_image_get_storage_type (image) != GTK_IMAGE_STOCK)
-    return FALSE;
-
-  gtk_stock_lookup (image->data.stock.stock_id, &stock);
-
-  if (should_show_image (image))
-    dbusmenu_menuitem_property_set (menuitem,
-                                    DBUSMENU_MENUITEM_PROP_ICON_NAME,
-                                    image->data.stock.stock_id);
-  else
-    dbusmenu_menuitem_property_remove (menuitem,
-                                       DBUSMENU_MENUITEM_PROP_ICON_NAME);
-
-  const gchar *label = dbusmenu_menuitem_property_get (menuitem,
-                                                       DBUSMENU_MENUITEM_PROP_LABEL);
-
-  if (stock.label != NULL && label != NULL)
-    {
-      dbusmenu_menuitem_property_set (menuitem,
-                                      DBUSMENU_MENUITEM_PROP_LABEL,
-                                      stock.label);
-
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
-static void
-update_icon_name (DbusmenuMenuitem *menuitem,
-                  GtkWidget        *widget)
-{
-  GtkImage *image;
-
-  g_return_if_fail (GTK_IS_IMAGE (widget));
-
-  image = GTK_IMAGE (widget);
-
-  if (gtk_image_get_storage_type (image) != GTK_IMAGE_ICON_NAME)
-    return;
-
-  if (should_show_image (image))
-    dbusmenu_menuitem_property_set (menuitem,
-                                    DBUSMENU_MENUITEM_PROP_ICON_NAME,
-                                    image->data.name.icon_name);
-  else
-    dbusmenu_menuitem_property_remove (menuitem,
-                                       DBUSMENU_MENUITEM_PROP_ICON_NAME);
-}
-
-static void
-widget_notify_cb (GtkWidget  *widget,
-                  GParamSpec *pspec,
-                  gpointer    data)
-{
-  DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
-
-  if (pspec->name == g_intern_static_string ("sensitive"))
-    {
-      dbusmenu_menuitem_property_set_bool (child,
-                                           DBUSMENU_MENUITEM_PROP_ENABLED,
-                                           gtk_widget_get_sensitive (widget));
-    }
-  else if (pspec->name == g_intern_static_string ("label"))
-    {
-      dbusmenu_menuitem_property_set (child,
-                                      DBUSMENU_MENUITEM_PROP_LABEL,
-                                      gtk_menu_item_get_label (GTK_MENU_ITEM (widget)));
-    }
-  else if (pspec->name == g_intern_static_string ("visible"))
-    {
-      dbusmenu_menuitem_property_set_bool (child,
-                                           DBUSMENU_MENUITEM_PROP_VISIBLE,
-                                           gtk_widget_get_visible (widget));
-    }
-  else if (pspec->name == g_intern_static_string ("stock"))
-    {
-      update_stock_item (child, widget);
-    }
-  else if (pspec->name == g_intern_static_string ("icon-name"))
-    {
-      update_icon_name (child, widget);
-    }
-  else if (pspec->name == g_intern_static_string ("parent"))
-    {
-      /*
-        * We probably should have added a 'remove' method to the
-        * UbuntuMenuProxy early on, but it's late in the cycle now.
-        */
-      if (gtk_widget_get_parent (widget) == NULL)
-        {
-          g_signal_handlers_disconnect_by_func (widget,
-                                                G_CALLBACK (widget_notify_cb),
-                                                child);
-
-          DbusmenuMenuitem *parent = g_object_get_data (G_OBJECT (child), "dbusmenu-parent");
-
-          if (DBUSMENU_IS_MENUITEM (parent) && DBUSMENU_IS_MENUITEM (child))
-            {
-              dbusmenu_menuitem_child_delete (parent, child);
-            }
-        }
-    }
-}
-
-static void
-label_notify_cb (GtkWidget  *widget,
-                 GParamSpec *pspec,
-                 gpointer    data)
-{
-  DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
-
-  if (pspec->name == g_intern_static_string ("label"))
-    {
-      dbusmenu_menuitem_property_set (child,
-                                      DBUSMENU_MENUITEM_PROP_LABEL,
-                                      gtk_label_get_text (GTK_LABEL (widget)));
-    }
-}
-
-static void
-menuitem_notify_cb (GtkWidget  *widget,
-                    GParamSpec *pspec,
-                    gpointer    data)
-{
-  if (pspec->name == g_intern_static_string ("visible"))
-    {
-      AppWindowContext *context = (AppWindowContext *)data;
-      GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
-      GtkWidget *window = NULL;
-
-      if (context != NULL)
-        window = context->window;
-
-      if (toplevel == window)
-        {
-          rebuild (context->bridge, window);
-        }
-
-      /* We only care about this once, so let's disconnect now. */
-      g_signal_handlers_disconnect_by_func (widget,
-                                            G_CALLBACK (menuitem_notify_cb),
-                                            data);
-    }
-}
-
-static void
-checkbox_toggled (GtkWidget *widget, DbusmenuMenuitem *mi)
-{
-  dbusmenu_menuitem_property_set_int (mi,
-                                      DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
-                                      gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
-}
-
-static void
-accel_changed (GtkWidget *widget,
-               gpointer   data)
-{
-  DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data;
-  dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget));
-}
-
-static void
-action_notify_cb (GtkAction  *action,
-                  GParamSpec *pspec,
-                  gpointer    data)
-{
-  DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data;
-
-  if (pspec->name == g_intern_static_string ("sensitive"))
-    {
-      dbusmenu_menuitem_property_set_bool (mi,
-                                           DBUSMENU_MENUITEM_PROP_ENABLED,
-                                           gtk_action_is_sensitive (action));
-    }
-  else if (pspec->name == g_intern_static_string ("visible"))
-    {
-      dbusmenu_menuitem_property_set_bool (mi,
-                                           DBUSMENU_MENUITEM_PROP_VISIBLE,
-                                           gtk_action_is_visible (action));
-    }
-  else if (pspec->name == g_intern_static_string ("active"))
-    {
-      dbusmenu_menuitem_property_set_bool (mi,
-                                           DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
-                                           gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
-    }
-  else if (pspec->name == g_intern_static_string ("label"))
-    {
-      dbusmenu_menuitem_property_set (mi,
-                                      DBUSMENU_MENUITEM_PROP_LABEL,
-                                      gtk_action_get_label (action));
-    }
-}
-
-static DbusmenuMenuitem *
-construct_dbusmenu_for_widget (GtkWidget *widget)
-{
-  DbusmenuMenuitem *mi = dbusmenu_menuitem_new ();
-
-  if (GTK_IS_MENU_ITEM (widget))
-    {
-      gboolean visible = FALSE;
-      gboolean sensitive = FALSE;
-      if (GTK_IS_SEPARATOR_MENU_ITEM (widget))
-        {
-          dbusmenu_menuitem_property_set (mi,
-                                          "type",
-                                          "separator");
-
-          visible = gtk_widget_get_visible (widget);
-          sensitive = gtk_widget_get_sensitive (widget);
-        }
-      else
-        {
-          gboolean label_set = FALSE;
-
-          g_signal_connect (widget,
-                            "accel-closures-changed",
-                            G_CALLBACK (accel_changed),
-                            mi);
-
-          if (GTK_IS_CHECK_MENU_ITEM (widget))
-            {
-              dbusmenu_menuitem_property_set (mi,
-                                              DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE,
-                                              gtk_check_menu_item_get_draw_as_radio (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_RADIO : DBUSMENU_MENUITEM_TOGGLE_CHECK);
-
-              dbusmenu_menuitem_property_set_int (mi,
-                                                  DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
-                                                  gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
-
-              g_signal_connect (widget,
-                                "activate",
-                                G_CALLBACK (checkbox_toggled),
-                                mi);
-            }
-
-          if (GTK_IS_IMAGE_MENU_ITEM (widget))
-            {
-              GtkWidget *image;
-              GtkImageType image_type;
-
-              image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget));
-
-              if (GTK_IS_IMAGE (image))
-                {
-                  image_type = gtk_image_get_storage_type (GTK_IMAGE (image));
-
-                  if (image_type == GTK_IMAGE_STOCK)
-                    {
-                      label_set = update_stock_item (mi, image);
-                    }
-                  else if (image_type == GTK_IMAGE_ICON_NAME)
-                    {
-                      update_icon_name (mi, image);
-                    }
-                  else if (image_type == GTK_IMAGE_PIXBUF)
-                    {
-                      dbusmenu_menuitem_property_set_image (mi,
-                                                            DBUSMENU_MENUITEM_PROP_ICON_DATA,
-                                                            gtk_image_get_pixbuf (GTK_IMAGE (image)));
-                    }
-                }
-            }
-
-          GtkWidget *label = find_menu_label (widget);
-
-          dbusmenu_menuitem_property_set (mi,
-                                          "label",
-                                          label ? gtk_label_get_text (GTK_LABEL (label)) : NULL);
-
-          if (label)
-            {
-              // Sometimes, an app will directly find and modify the label
-              // (like empathy), so watch the label especially for that.
-              g_signal_connect (G_OBJECT (label),
-                                "notify",
-                                G_CALLBACK (label_notify_cb),
-                                mi);
-            }
-
-          if (GTK_IS_ACTIVATABLE (widget))
-            {
-              GtkActivatable *activatable = GTK_ACTIVATABLE (widget);
-
-              if (gtk_activatable_get_use_action_appearance (activatable))
-                {
-                  GtkAction *action = gtk_activatable_get_related_action (activatable);
-
-                  if (action)
-                    {
-                      visible = gtk_action_is_visible (action);
-                      sensitive = gtk_action_is_sensitive (action);
-
-                      g_signal_connect_object (action, "notify",
-                                               G_CALLBACK (action_notify_cb),
-                                               mi,
-                                               G_CONNECT_AFTER);
-                    }
-                }
-            }
-
-          if (!g_object_get_data (G_OBJECT (widget), "gtk-empty-menu-item") && !GTK_IS_TEAROFF_MENU_ITEM (widget))
-            {
-              visible = gtk_widget_get_visible (widget);
-              sensitive = gtk_widget_get_sensitive (widget);
-            }
-
-          dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget));
-
-          g_signal_connect (G_OBJECT (mi),
-                            DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
-                            G_CALLBACK (item_activated),
-                            widget);
-
-          g_signal_connect (G_OBJECT (mi),
-                            DBUSMENU_MENUITEM_SIGNAL_ABOUT_TO_SHOW,
-                            G_CALLBACK (item_about_to_show),
-                            widget);
-        }
-
-      dbusmenu_menuitem_property_set_bool (mi,
-                                           DBUSMENU_MENUITEM_PROP_VISIBLE,
-                                           visible);
-
-      dbusmenu_menuitem_property_set_bool (mi,
-                                           DBUSMENU_MENUITEM_PROP_ENABLED,
-                                           sensitive);
-
-      g_signal_connect (widget,
-                        "notify",
-                        G_CALLBACK (widget_notify_cb),
-                        mi);
-    }
-
-  return mi;
-}
-
-static void
-rebuild_item (GtkWidget      *widget,
-              RecurseContext *recurse)
-{
-  if (GTK_IS_CONTAINER (widget))
-    {
-      gboolean increment = GTK_IS_MENU_BAR (widget) || GTK_IS_MENU_ITEM (widget);
-
-      if (increment)
-        recurse->count++;
-
-      /* Okay, this is a little janky and all.. but some applications update some
-       * menuitem properties such as sensitivity on the activate callback.  This
-       * seems a little weird, but it's not our place to judge when all this code
-       * is so crazy.  So we're going to get ever crazier and activate all the
-       * menus that are directly below the menubar and force the applications to
-       * update their sensitivity.  The menus won't actually popup in the app
-       * window due to our gtk+ patches.
-       *
-       * Note that this will not force menuitems in submenus to be updated as well.
-       */
-      if (recurse->count == 0 && GTK_IS_MENU_BAR (widget))
-        {
-          GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
-
-          for (; children != NULL; children = children->next)
-            {
-              gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget),
-                                            children->data,
-                                            TRUE);
-            }
-
-          g_list_free (children);
-        }
-
-      if (recurse->count > -1 && increment)
-        {
-          DbusmenuMenuitem *dmi = g_hash_table_lookup (recurse->context->lookup, widget);
-          if (dmi != NULL)
-            {
-              if (increment)
-                recurse->count--;
-
-              return;
-            }
-          else
-            {
-              recurse->stack[recurse->count] = construct_dbusmenu_for_widget (widget);
-              g_hash_table_insert (recurse->context->lookup, widget, recurse->stack[recurse->count]);
-            }
-
-          if (!gtk_widget_get_visible (widget))
-            {
-              g_signal_connect (G_OBJECT (widget),
-                                "notify",
-                                G_CALLBACK (menuitem_notify_cb),
-                                recurse->context);
-            }
-
-          if (GTK_IS_TEAROFF_MENU_ITEM (widget))
-            {
-              dbusmenu_menuitem_property_set_bool (recurse->stack[recurse->count],
-                                                   DBUSMENU_MENUITEM_PROP_VISIBLE,
-                                                   FALSE);
-            }
-
-          if (recurse->count > 0)
-            {
-              GList *children = NULL;
-              GList *peek = NULL;
-
-              if (recurse->stack[recurse->count - 1])
-                {
-                  children = dbusmenu_menuitem_get_children (recurse->stack[recurse->count - 1]);
-
-                  if (children)
-                    {
-                      peek = g_list_find (children, recurse->stack[recurse->count]);
-                    }
-
-                  if (!peek)
-                    {
-                      /* Should we set a weak ref on the parent? */
-                      g_object_set_data (G_OBJECT (recurse->stack[recurse->count]),
-                                         "dbusmenu-parent",
-                                         recurse->stack[recurse->count - 1]);
-                      dbusmenu_menuitem_child_append (recurse->stack[recurse->count - 1],
-                                                      recurse->stack[recurse->count]);
-                    }
-                }
-              else
-                {
-                  DbusmenuMenuitem *item = g_hash_table_lookup (recurse->context->lookup,
-                                                                gtk_widget_get_parent (widget));
-
-                  if (item)
-                    {
-                      children = dbusmenu_menuitem_get_children (item);
-
-                      if (children)
-                        {
-                          peek = g_list_find (children, recurse->stack[recurse->count]);
-                        }
-
-                      if (!peek)
-                        {
-                          g_object_set_data (G_OBJECT (recurse->stack[recurse->count]),
-                                             "dbusmenu-parent",
-                                             recurse->stack[recurse->count - 1]);
-
-                          dbusmenu_menuitem_child_append (item, recurse->stack[recurse->count]);
-                        }
-                    }
-                }
-            }
-        }
-
-      gtk_container_foreach (GTK_CONTAINER (widget),
-                             (GtkCallback)rebuild_item,
-                             recurse);
-
-      if (GTK_IS_MENU_ITEM (widget))
-        {
-          GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
-
-          if (menu != NULL)
-            {
-              rebuild_item (menu, recurse);
-            }
-        }
-
-      if (increment)
-        recurse->count--;
-    }
-}
-
 typedef struct _RebuildData {
   AppMenuBridge *bridge;
   GtkWidget     *widget;
@@ -1076,15 +492,48 @@
   g_hash_table_insert (rebuild_ids, toplevel, GUINT_TO_POINTER (id));
 }
 
+static DbusmenuMenuitem * find_menu_bar (GtkWidget * widget);
+
+static void
+find_menu_bar_helper (GtkWidget * widget, gpointer data)
+{
+	DbusmenuMenuitem ** mi = (DbusmenuMenuitem **)data;
+
+	/* We've already found a menu, let's get through the
+	   foreach as quickly as possible */
+	if (*mi != NULL) {
+		return;
+	}
+
+	*mi = find_menu_bar(widget);
+	return;
+}
+
+static DbusmenuMenuitem *
+find_menu_bar (GtkWidget * widget)
+{
+	if (GTK_IS_MENU_BAR(widget) || GTK_IS_MENU_ITEM(widget)) {
+		return dbusmenu_gtk_parse_menu_structure(widget);
+	}
+
+	if (GTK_IS_CONTAINER(widget)) {
+		DbusmenuMenuitem * mi = NULL;
+
+		gtk_container_foreach(GTK_CONTAINER(widget), find_menu_bar_helper, &mi);
+
+		return mi;
+	}
+
+	return NULL;
+}
+
+
 static void
 rebuild_window_items (AppMenuBridge *bridge,
                       GtkWidget     *toplevel)
 {
   XID xid;
   AppWindowContext *context = NULL;
-  RecurseContext recurse;
-
-  memset (&recurse, 0, sizeof (RecurseContext));
 
   if (!GTK_IS_WINDOW (toplevel))
     {
@@ -1147,14 +596,6 @@
       context->bridge = bridge;
       context->lookup = g_hash_table_new (g_direct_hash, g_direct_equal);
       bridge->priv->windows = g_list_prepend (bridge->priv->windows, context);
-
-      recurse.previous = FALSE;
-      recurse.count    = -1;
-    }
-  else
-    {
-      recurse.previous = TRUE;
-      recurse.count    = 0;
     }
 
   if (context->window)
@@ -1183,24 +624,15 @@
   if (!context->server)
     context->server = dbusmenu_server_new (context->path);
 
-  recurse.bridge  = bridge;
-  recurse.context = context;
-
-  gtk_container_foreach (GTK_CONTAINER (toplevel),
-                         (GtkCallback)rebuild_item,
-                         &recurse);
-
-  if (recurse.stack[0] != NULL && DBUSMENU_IS_MENUITEM (recurse.stack[0]))
-    {
-      context->root = recurse.stack[0];
-
-      dbusmenu_server_set_root (context->server, context->root);
-    }
+  DbusmenuMenuitem * mi = find_menu_bar(toplevel);
+  dbusmenu_server_set_root(context->server, mi);
+  if (mi != NULL) {
+    g_object_unref(G_OBJECT(mi));
+  }
 
   register_application_windows (bridge);
 }
 
-
 static void
 toplevel_realized (GtkWidget *widget,
                    gpointer   user_data)
@@ -1316,7 +748,7 @@
 
           if (mi != NULL)
             {
-              DbusmenuMenuitem *child_dmi = construct_dbusmenu_for_widget (child);
+              DbusmenuMenuitem *child_dmi = dbusmenu_gtk_parse_menu_structure (child);
 
               g_object_set_data (G_OBJECT (child_dmi), "dbusmenu-parent", mi);
               dbusmenu_menuitem_child_add_position (mi,


Follow ups