diff options
author | Ted Gould <ted@gould.cx> | 2011-03-31 13:48:12 -0500 |
---|---|---|
committer | Ted Gould <ted@gould.cx> | 2011-03-31 13:48:12 -0500 |
commit | 269670511328aada39a23bd982a1ca3a44de9cfe (patch) | |
tree | 48a6c86d5e51e3b7ec2f0c9446115c2142e8cd8a /libdbusmenu-gtk | |
parent | 53691e5c73a343fec78e6782089e092bd6bcd3ac (diff) | |
parent | f90465d8892aff9002874ae40656b3c67a2542af (diff) | |
download | libdbusmenu-269670511328aada39a23bd982a1ca3a44de9cfe.tar.gz libdbusmenu-269670511328aada39a23bd982a1ca3a44de9cfe.tar.bz2 libdbusmenu-269670511328aada39a23bd982a1ca3a44de9cfe.zip |
Import upstream version 0.4.1
Diffstat (limited to 'libdbusmenu-gtk')
-rw-r--r-- | libdbusmenu-gtk/menuitem.c | 21 | ||||
-rw-r--r-- | libdbusmenu-gtk/parser.c | 98 |
2 files changed, 98 insertions, 21 deletions
diff --git a/libdbusmenu-gtk/menuitem.c b/libdbusmenu-gtk/menuitem.c index ca2bc3e..0f511bc 100644 --- a/libdbusmenu-gtk/menuitem.c +++ b/libdbusmenu-gtk/menuitem.c @@ -275,6 +275,17 @@ dbusmenu_menuitem_property_set_shortcut_menuitem (DbusmenuMenuitem * menuitem, c void dbusmenu_menuitem_property_get_shortcut (DbusmenuMenuitem * menuitem, guint * key, GdkModifierType * modifier) { + guint dummykey; + GdkModifierType dummymodifier; + + if (key == NULL) { + key = &dummykey; + } + + if (modifier == NULL) { + modifier = &dummymodifier; + } + *key = 0; *modifier = 0; @@ -287,15 +298,15 @@ dbusmenu_menuitem_property_get_shortcut (DbusmenuMenuitem * menuitem, guint * ke if (g_variant_n_children(wrapper) != 1) { g_warning("Unable to parse shortcut, too many keys"); - g_variant_unref(wrapper); return; } GVariantIter iter; - g_variant_iter_init(&iter, g_variant_get_child_value(wrapper, 0)); + GVariant * child = g_variant_get_child_value(wrapper, 0); + g_variant_iter_init(&iter, child); gchar * string; - while(g_variant_iter_next(&iter, "s", &string)) { + while(g_variant_iter_loop(&iter, "s", &string)) { if (g_strcmp0(string, DBUSMENU_MENUITEM_SHORTCUT_CONTROL) == 0) { *modifier |= GDK_CONTROL_MASK; } else if (g_strcmp0(string, DBUSMENU_MENUITEM_SHORTCUT_ALT) == 0) { @@ -308,10 +319,10 @@ dbusmenu_menuitem_property_get_shortcut (DbusmenuMenuitem * menuitem, guint * ke GdkModifierType tempmod; gtk_accelerator_parse(string, key, &tempmod); } - - g_free(string); } + g_variant_unref(child); + return; } diff --git a/libdbusmenu-gtk/parser.c b/libdbusmenu-gtk/parser.c index a7f90a2..e68c286 100644 --- a/libdbusmenu-gtk/parser.c +++ b/libdbusmenu-gtk/parser.c @@ -454,7 +454,7 @@ construct_dbusmenu_for_widget (GtkWidget * widget) gboolean visible = FALSE; gboolean sensitive = FALSE; - if (GTK_IS_SEPARATOR_MENU_ITEM (widget)) + if (GTK_IS_SEPARATOR_MENU_ITEM (widget) || !find_menu_label (widget)) { dbusmenu_menuitem_property_set (mi, "type", @@ -512,21 +512,18 @@ construct_dbusmenu_for_widget (GtkWidget * widget) GtkWidget *label = find_menu_label (widget); - if (label) - { - // Sometimes, an app will directly find and modify the label - // (like empathy), so watch the label especially for that. - gchar * text = sanitize_label (GTK_LABEL (label)); - dbusmenu_menuitem_property_set (mi, "label", text); - g_free (text); - - pdata->label = label; - g_signal_connect (G_OBJECT (label), - "notify", - G_CALLBACK (label_notify_cb), - mi); - g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label); - } + // Sometimes, an app will directly find and modify the label + // (like empathy), so watch the label especially for that. + gchar * text = sanitize_label (GTK_LABEL (label)); + dbusmenu_menuitem_property_set (mi, "label", text); + g_free (text); + + pdata->label = label; + g_signal_connect (G_OBJECT (label), + "notify", + G_CALLBACK (label_notify_cb), + mi); + g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label); if (GTK_IS_ACTIVATABLE (widget)) { @@ -760,11 +757,48 @@ find_menu_label (GtkWidget *widget) } static void +recreate_menu_item (DbusmenuMenuitem * parent, DbusmenuMenuitem * child) +{ + if (parent == NULL) + { + /* We need a parent */ + return; + } + 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); +} + +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); + recreate_menu_item (parent, child); + 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")) { @@ -774,6 +808,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 @@ -891,6 +943,20 @@ widget_notify_cb (GtkWidget *widget, } else if (pspec->name == g_intern_static_string ("label")) { + 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. + * As changing types isn't handled too well by the client, we delete + * this menuitem for now and then recreate it + */ + DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (child); + recreate_menu_item (parent, child); + return; + } + dbusmenu_menuitem_property_set (child, DBUSMENU_MENUITEM_PROP_LABEL, g_value_get_string (&prop_value)); |