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
1=== modified file 'libdbusmenu-glib/defaults.c'
2--- libdbusmenu-glib/defaults.c 2011-02-25 14:47:56 +0000
3+++ libdbusmenu-glib/defaults.c 2011-03-30 19:01:23 +0000
4@@ -81,7 +81,7 @@
5 /* Standard defaults */
6 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_VISIBLE, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
7 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ENABLED, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
8- dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_LABEL, G_VARIANT_TYPE_STRING, g_variant_new_string(_("Label Empty")));
9+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_LABEL, G_VARIANT_TYPE_STRING, g_variant_new_string(_("Label Empty")));
10 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ICON_NAME, G_VARIANT_TYPE_STRING, NULL);
11 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, G_VARIANT_TYPE_STRING, NULL);
12 dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, G_VARIANT_TYPE_INT32, NULL);
13
14=== modified file 'libdbusmenu-gtk/parser.c'
15--- libdbusmenu-gtk/parser.c 2011-03-21 14:00:36 +0000
16+++ libdbusmenu-gtk/parser.c 2011-03-30 19:01:23 +0000
17@@ -454,7 +454,7 @@
18
19 gboolean visible = FALSE;
20 gboolean sensitive = FALSE;
21- if (GTK_IS_SEPARATOR_MENU_ITEM (widget))
22+ if (GTK_IS_SEPARATOR_MENU_ITEM (widget) || !find_menu_label (widget))
23 {
24 dbusmenu_menuitem_property_set (mi,
25 "type",
26@@ -512,21 +512,18 @@
27
28 GtkWidget *label = find_menu_label (widget);
29
30- if (label)
31- {
32- // Sometimes, an app will directly find and modify the label
33- // (like empathy), so watch the label especially for that.
34- gchar * text = sanitize_label (GTK_LABEL (label));
35- dbusmenu_menuitem_property_set (mi, "label", text);
36- g_free (text);
37+ // Sometimes, an app will directly find and modify the label
38+ // (like empathy), so watch the label especially for that.
39+ gchar * text = sanitize_label (GTK_LABEL (label));
40+ dbusmenu_menuitem_property_set (mi, "label", text);
41+ g_free (text);
42
43- pdata->label = label;
44- g_signal_connect (G_OBJECT (label),
45- "notify",
46- G_CALLBACK (label_notify_cb),
47- mi);
48- g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label);
49- }
50+ pdata->label = label;
51+ g_signal_connect (G_OBJECT (label),
52+ "notify",
53+ G_CALLBACK (label_notify_cb),
54+ mi);
55+ g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label);
56
57 if (GTK_IS_ACTIVATABLE (widget))
58 {
59@@ -760,11 +757,48 @@
60 }
61
62 static void
63+recreate_menu_item (DbusmenuMenuitem * parent, DbusmenuMenuitem * child)
64+{
65+ if (parent == NULL)
66+ {
67+ /* We need a parent */
68+ return;
69+ }
70+ ParserData * pdata = g_object_get_data (G_OBJECT (child), PARSER_DATA);
71+ /* Keep a pointer to the GtkMenuItem, as pdata->widget might be
72+ * invalidated when we delete the DbusmenuMenuitem
73+ */
74+ GtkWidget * menuitem = pdata->widget;
75+
76+ dbusmenu_menuitem_child_delete (parent, child);
77+
78+ RecurseContext recurse = {0};
79+ recurse.toplevel = gtk_widget_get_toplevel(menuitem);
80+ recurse.parent = parent;
81+
82+ parse_menu_structure_helper(menuitem, &recurse);
83+}
84+
85+static gboolean
86+recreate_menu_item_in_idle_cb (gpointer data)
87+{
88+ DbusmenuMenuitem * child = (DbusmenuMenuitem *)data;
89+ DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (child);
90+ g_object_unref (child);
91+ recreate_menu_item (parent, child);
92+ return FALSE;
93+}
94+
95+static void
96 label_notify_cb (GtkWidget *widget,
97 GParamSpec *pspec,
98 gpointer data)
99 {
100 DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
101+ GValue prop_value = {0};
102+
103+ g_value_init (&prop_value, pspec->value_type);
104+ g_object_get_property (G_OBJECT (widget), pspec->name, &prop_value);
105
106 if (pspec->name == g_intern_static_string ("label"))
107 {
108@@ -774,6 +808,24 @@
109 text);
110 g_free (text);
111 }
112+ else if (pspec->name == g_intern_static_string ("parent"))
113+ {
114+ if (GTK_WIDGET (g_value_get_object (&prop_value)) == NULL)
115+ {
116+ /* This label is being removed from its GtkMenuItem. The
117+ * menuitem becomes a separator now. As the client doesn't handle
118+ * changing types so well, we remove the current DbusmenuMenuitem
119+ * and add a new one.
120+ *
121+ * Note, we have to defer this to idle, as we are called before
122+ * bin->child member of our old parent is invalidated. If we go ahead
123+ * and call parse_menu_structure_helper now, the GtkMenuItem will
124+ * still appear to have a label and we never convert it to a separator
125+ */
126+ g_object_ref (child);
127+ g_idle_add ((GSourceFunc)recreate_menu_item_in_idle_cb, child);
128+ }
129+ }
130 }
131
132 static void
133@@ -891,6 +943,20 @@
134 }
135 else if (pspec->name == g_intern_static_string ("label"))
136 {
137+ ParserData *pdata = g_object_get_data (G_OBJECT (child), PARSER_DATA);
138+ if (!pdata->label)
139+ {
140+ /* GtkMenuItem's can start life as a separator if they have no child
141+ * GtkLabel. In this case, we need to convert the DbusmenuMenuitem from
142+ * a separator to a normal menuitem if the application adds a label.
143+ * As changing types isn't handled too well by the client, we delete
144+ * this menuitem for now and then recreate it
145+ */
146+ DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (child);
147+ recreate_menu_item (parent, child);
148+ return;
149+ }
150+
151 dbusmenu_menuitem_property_set (child,
152 DBUSMENU_MENUITEM_PROP_LABEL,
153 g_value_get_string (&prop_value));

Subscribers

People subscribed via source and target branches