aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-gtk/parser.c
diff options
context:
space:
mode:
authorChris Coulson <chrisccoulson@ubuntu.com>2011-03-30 19:43:02 +0100
committerChris Coulson <chrisccoulson@ubuntu.com>2011-03-30 19:43:02 +0100
commit25b78133a2075185fe2d94925f446927c1b85b9a (patch)
tree5732fe6e8621be826d4f82d20769b21324591ec9 /libdbusmenu-gtk/parser.c
parentf4bfda45834ee6f3983be3e3d7fd9c0e8fb7512e (diff)
downloadlibdbusmenu-25b78133a2075185fe2d94925f446927c1b85b9a.tar.gz
libdbusmenu-25b78133a2075185fe2d94925f446927c1b85b9a.tar.bz2
libdbusmenu-25b78133a2075185fe2d94925f446927c1b85b9a.zip
- 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
Diffstat (limited to 'libdbusmenu-gtk/parser.c')
-rw-r--r--libdbusmenu-gtk/parser.c74
1 files changed, 62 insertions, 12 deletions
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,