Merge lp:~chrisccoulson/libdbusmenu/lp729187 into lp:libdbusmenu/0.5

Proposed by Chris Coulson
Status: Merged
Merged at revision: 285
Proposed branch: lp:~chrisccoulson/libdbusmenu/lp729187
Merge into: lp:libdbusmenu/0.5
Diff against target: 153 lines (+82/-16)
2 files modified
libdbusmenu-glib/defaults.c (+1/-1)
libdbusmenu-gtk/parser.c (+81/-15)
To merge this branch: bzr merge lp:~chrisccoulson/libdbusmenu/lp729187
Reviewer Review Type Date Requested Status
Chris Coulson (community) Needs Resubmitting
Ted Gould (community) Needs Fixing
Review via email: mp+55399@code.launchpad.net

Description of the change

Don't set a default label for menuitems. Some applications (eg, xchat and pidgin) do silly things like creating GtkMenuItems's without a label for separators (rather than using the GtkSeparatorMenuItem class).

GTK correctly renders these as separators, so we need to handle it too by not setting a default label on these

To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote :

I think we're going to have to detect this case in the parser unfortunately. The Qt and Nux implementations of Dbusmenu won't correctly view them as separators.

review: Needs Fixing
284. By Chris Coulson

Revert the last commit and handle the same problem in the parser instead

285. By Chris Coulson

Remove the now unneeded null pointer check on label in construct_dbusmenu_for_widget.
Also, don't use a strcmp in widget_notify_cb for checking if the menuitem is a separator. Just do a null pointer
check on pdata->label instead

Revision history for this message
Chris Coulson (chrisccoulson) wrote :

Ok, I've implemented the check in the parser now

review: Needs Resubmitting
Revision history for this message
Chris Coulson (chrisccoulson) wrote :

Oops, that was meant to be "Comment only"

Revision history for this message
Ted Gould (ted) wrote :

So, while I think this code is fine. I think that client code doesn't
handle changing types well. It could probably be fixed, but I think
that an easier solution might be to just destroy the dbusmenu item and
create a new one if we get a label after making a separator. What do
you think there?

Also, is there a use case for the label getting removed that it'd go
back to being a separator? Seems like *really* bad usage, but I'm
curious if we need to handle that case as well.

286. By Chris Coulson

- 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

Revision history for this message
Chris Coulson (chrisccoulson) wrote :

Ok, I've fixed it to destroy the existing menuitem and recreate it, rather than changing the type of the existing one. It also handles being converted back to a separator now (which can happen if someone calls gtk_container_remove to remove the label from the menuitem)

287. By Chris Coulson

Remove some code duplication introduced in this branch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libdbusmenu-glib/defaults.c'
--- libdbusmenu-glib/defaults.c 2011-02-25 14:47:56 +0000
+++ libdbusmenu-glib/defaults.c 2011-03-30 19:01:23 +0000
@@ -81,7 +81,7 @@
81 /* Standard defaults */81 /* Standard defaults */
82 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_VISIBLE, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE)); 82 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_VISIBLE, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
83 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ENABLED, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE)); 83 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ENABLED, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
84 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_LABEL, G_VARIANT_TYPE_STRING, g_variant_new_string(_("Label Empty"))); 84 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_LABEL, G_VARIANT_TYPE_STRING, g_variant_new_string(_("Label Empty")));
85 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ICON_NAME, G_VARIANT_TYPE_STRING, NULL); 85 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ICON_NAME, G_VARIANT_TYPE_STRING, NULL);
86 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, G_VARIANT_TYPE_STRING, NULL); 86 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, G_VARIANT_TYPE_STRING, NULL);
87 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, G_VARIANT_TYPE_INT32, NULL); 87 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, G_VARIANT_TYPE_INT32, NULL);
8888
=== modified file 'libdbusmenu-gtk/parser.c'
--- libdbusmenu-gtk/parser.c 2011-03-21 14:00:36 +0000
+++ libdbusmenu-gtk/parser.c 2011-03-30 19:01:23 +0000
@@ -454,7 +454,7 @@
454454
455 gboolean visible = FALSE;455 gboolean visible = FALSE;
456 gboolean sensitive = FALSE;456 gboolean sensitive = FALSE;
457 if (GTK_IS_SEPARATOR_MENU_ITEM (widget))457 if (GTK_IS_SEPARATOR_MENU_ITEM (widget) || !find_menu_label (widget))
458 {458 {
459 dbusmenu_menuitem_property_set (mi,459 dbusmenu_menuitem_property_set (mi,
460 "type",460 "type",
@@ -512,21 +512,18 @@
512512
513 GtkWidget *label = find_menu_label (widget);513 GtkWidget *label = find_menu_label (widget);
514514
515 if (label)515 // Sometimes, an app will directly find and modify the label
516 {516 // (like empathy), so watch the label especially for that.
517 // Sometimes, an app will directly find and modify the label517 gchar * text = sanitize_label (GTK_LABEL (label));
518 // (like empathy), so watch the label especially for that.518 dbusmenu_menuitem_property_set (mi, "label", text);
519 gchar * text = sanitize_label (GTK_LABEL (label));519 g_free (text);
520 dbusmenu_menuitem_property_set (mi, "label", text);
521 g_free (text);
522520
523 pdata->label = label;521 pdata->label = label;
524 g_signal_connect (G_OBJECT (label),522 g_signal_connect (G_OBJECT (label),
525 "notify",523 "notify",
526 G_CALLBACK (label_notify_cb),524 G_CALLBACK (label_notify_cb),
527 mi);525 mi);
528 g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label);526 g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label);
529 }
530527
531 if (GTK_IS_ACTIVATABLE (widget))528 if (GTK_IS_ACTIVATABLE (widget))
532 {529 {
@@ -760,11 +757,48 @@
760}757}
761758
762static void759static void
760recreate_menu_item (DbusmenuMenuitem * parent, DbusmenuMenuitem * child)
761{
762 if (parent == NULL)
763 {
764 /* We need a parent */
765 return;
766 }
767 ParserData * pdata = g_object_get_data (G_OBJECT (child), PARSER_DATA);
768 /* Keep a pointer to the GtkMenuItem, as pdata->widget might be
769 * invalidated when we delete the DbusmenuMenuitem
770 */
771 GtkWidget * menuitem = pdata->widget;
772
773 dbusmenu_menuitem_child_delete (parent, child);
774
775 RecurseContext recurse = {0};
776 recurse.toplevel = gtk_widget_get_toplevel(menuitem);
777 recurse.parent = parent;
778
779 parse_menu_structure_helper(menuitem, &recurse);
780}
781
782static gboolean
783recreate_menu_item_in_idle_cb (gpointer data)
784{
785 DbusmenuMenuitem * child = (DbusmenuMenuitem *)data;
786 DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (child);
787 g_object_unref (child);
788 recreate_menu_item (parent, child);
789 return FALSE;
790}
791
792static void
763label_notify_cb (GtkWidget *widget,793label_notify_cb (GtkWidget *widget,
764 GParamSpec *pspec,794 GParamSpec *pspec,
765 gpointer data)795 gpointer data)
766{796{
767 DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;797 DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
798 GValue prop_value = {0};
799
800 g_value_init (&prop_value, pspec->value_type);
801 g_object_get_property (G_OBJECT (widget), pspec->name, &prop_value);
768802
769 if (pspec->name == g_intern_static_string ("label"))803 if (pspec->name == g_intern_static_string ("label"))
770 {804 {
@@ -774,6 +808,24 @@
774 text);808 text);
775 g_free (text);809 g_free (text);
776 }810 }
811 else if (pspec->name == g_intern_static_string ("parent"))
812 {
813 if (GTK_WIDGET (g_value_get_object (&prop_value)) == NULL)
814 {
815 /* This label is being removed from its GtkMenuItem. The
816 * menuitem becomes a separator now. As the client doesn't handle
817 * changing types so well, we remove the current DbusmenuMenuitem
818 * and add a new one.
819 *
820 * Note, we have to defer this to idle, as we are called before
821 * bin->child member of our old parent is invalidated. If we go ahead
822 * and call parse_menu_structure_helper now, the GtkMenuItem will
823 * still appear to have a label and we never convert it to a separator
824 */
825 g_object_ref (child);
826 g_idle_add ((GSourceFunc)recreate_menu_item_in_idle_cb, child);
827 }
828 }
777}829}
778830
779static void831static void
@@ -891,6 +943,20 @@
891 }943 }
892 else if (pspec->name == g_intern_static_string ("label"))944 else if (pspec->name == g_intern_static_string ("label"))
893 {945 {
946 ParserData *pdata = g_object_get_data (G_OBJECT (child), PARSER_DATA);
947 if (!pdata->label)
948 {
949 /* GtkMenuItem's can start life as a separator if they have no child
950 * GtkLabel. In this case, we need to convert the DbusmenuMenuitem from
951 * a separator to a normal menuitem if the application adds a label.
952 * As changing types isn't handled too well by the client, we delete
953 * this menuitem for now and then recreate it
954 */
955 DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (child);
956 recreate_menu_item (parent, child);
957 return;
958 }
959
894 dbusmenu_menuitem_property_set (child,960 dbusmenu_menuitem_property_set (child,
895 DBUSMENU_MENUITEM_PROP_LABEL,961 DBUSMENU_MENUITEM_PROP_LABEL,
896 g_value_get_string (&prop_value));962 g_value_get_string (&prop_value));

Subscribers

People subscribed via source and target branches