From 25b78133a2075185fe2d94925f446927c1b85b9a Mon Sep 17 00:00:00 2001 From: Chris Coulson Date: Wed, 30 Mar 2011 19:43:02 +0100 Subject: - Don't change the type of existing menu items in the server. This isn't handled in the client too well - Handle a GtkMenuItem's GtkLabel being removed too --- libdbusmenu-gtk/parser.c | 74 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 12 deletions(-) (limited to 'libdbusmenu-gtk/parser.c') diff --git a/libdbusmenu-gtk/parser.c b/libdbusmenu-gtk/parser.c index fc9a3fe..037c362 100644 --- a/libdbusmenu-gtk/parser.c +++ b/libdbusmenu-gtk/parser.c @@ -756,12 +756,43 @@ find_menu_label (GtkWidget *widget) return label; } +static gboolean +recreate_menu_item_in_idle_cb (gpointer data) +{ + DbusmenuMenuitem * child = (DbusmenuMenuitem *)data; + DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (child); + g_object_unref (child); + if (parent == NULL) + { + return FALSE; + } + ParserData * pdata = g_object_get_data (G_OBJECT (child), PARSER_DATA); + /* Keep a pointer to the GtkMenuItem, as pdata->widget might be + * invalidated when we delete the DbusmenuMenuitem + */ + GtkWidget * menuitem = pdata->widget; + + dbusmenu_menuitem_child_delete (parent, child); + + RecurseContext recurse = {0}; + recurse.toplevel = gtk_widget_get_toplevel(menuitem); + recurse.parent = parent; + + parse_menu_structure_helper(menuitem, &recurse); + + return FALSE; +} + static void label_notify_cb (GtkWidget *widget, GParamSpec *pspec, gpointer data) { DbusmenuMenuitem *child = (DbusmenuMenuitem *)data; + GValue prop_value = {0}; + + g_value_init (&prop_value, pspec->value_type); + g_object_get_property (G_OBJECT (widget), pspec->name, &prop_value); if (pspec->name == g_intern_static_string ("label")) { @@ -771,6 +802,24 @@ label_notify_cb (GtkWidget *widget, text); g_free (text); } + else if (pspec->name == g_intern_static_string ("parent")) + { + if (GTK_WIDGET (g_value_get_object (&prop_value)) == NULL) + { + /* This label is being removed from its GtkMenuItem. The + * menuitem becomes a separator now. As the client doesn't handle + * changing types so well, we remove the current DbusmenuMenuitem + * and add a new one. + * + * Note, we have to defer this to idle, as we are called before + * bin->child member of our old parent is invalidated. If we go ahead + * and call parse_menu_structure_helper now, the GtkMenuItem will + * still appear to have a label and we never convert it to a separator + */ + g_object_ref (child); + g_idle_add ((GSourceFunc)recreate_menu_item_in_idle_cb, child); + } + } } static void @@ -888,24 +937,25 @@ widget_notify_cb (GtkWidget *widget, } else if (pspec->name == g_intern_static_string ("label")) { - ParserData *pdata = g_object_get_data (G_OBJECT (widget), PARSER_DATA); + ParserData *pdata = g_object_get_data (G_OBJECT (child), PARSER_DATA); if (!pdata->label) { /* GtkMenuItem's can start life as a separator if they have no child * GtkLabel. In this case, we need to convert the DbusmenuMenuitem from - * a separator to a normal menuitem if the application adds a label + * a separator to a normal menuitem if the application adds a label. + * As changing types isn't handled too well by the client, we delete + * this menuitem for now and then recreate it */ - GtkWidget *label = find_menu_label (widget); - /* This should never fail */ - g_return_if_fail (label != NULL); + DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (child); + dbusmenu_menuitem_child_delete (parent, child); - dbusmenu_menuitem_property_remove (child, DBUSMENU_MENUITEM_PROP_TYPE); - pdata->label = label; - g_signal_connect (G_OBJECT (label), - "notify", - G_CALLBACK (label_notify_cb), - child); - g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label); + RecurseContext recurse = {0}; + recurse.toplevel = gtk_widget_get_toplevel(widget); + recurse.parent = parent; + + parse_menu_structure_helper(widget, &recurse); + + return; } dbusmenu_menuitem_property_set (child, -- cgit v1.2.3