Merge lp:~bratsche/appmenu-gtk/uimanager-fixes into lp:appmenu-gtk/0.4

Proposed by Cody Russell
Status: Merged
Merged at revision: 45
Proposed branch: lp:~bratsche/appmenu-gtk/uimanager-fixes
Merge into: lp:appmenu-gtk/0.4
Diff against target: 164 lines (+73/-22)
1 file modified
src/bridge.c (+73/-22)
To merge this branch: bzr merge lp:~bratsche/appmenu-gtk/uimanager-fixes
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+29045@code.launchpad.net

Description of the change

This fixes a number of issues that occur when building menus from GtkUIManager, including empty submenus in wrong places (see the Quit menu in Anjuta), crashes (see the File menu in Nautilus). It reverts the change in revision 30 where we skip separators that follow other separators (this was actually the cause of the Nautilus crash), and instead adds all separators and marks invisible the ones which are actually placeholders/smart separators.

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

Looks good. Not for this review but I'm curious if we shoudln't replace the "recurse" variable with a GArray?

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/bridge.c'
2--- src/bridge.c 2010-06-29 16:08:41 +0000
3+++ src/bridge.c 2010-07-02 02:00:43 +0000
4@@ -92,8 +92,15 @@
5
6 gint count;
7 DbusmenuMenuitem *stack[30];
8+ gboolean mode[30];
9 } RecurseContext;
10
11+enum {
12+ SEPARATOR_MODE_SMART,
13+ SEPARATOR_MODE_VISIBLE,
14+ SEPARATOR_MODE_HIDDEN
15+};
16+
17 G_DEFINE_DYNAMIC_TYPE(AppMenuBridge, app_menu_bridge, UBUNTU_TYPE_MENU_PROXY)
18
19 static guint rebuild_id = 0;
20@@ -448,7 +455,7 @@
21 }
22
23 static DbusmenuMenuitem *
24-construct_dbusmenu_for_widget (GtkWidget *widget)
25+construct_dbusmenu_for_widget (GtkWidget *widget, gboolean previous_separator)
26 {
27 DbusmenuMenuitem *mi = dbusmenu_menuitem_new ();
28
29@@ -459,9 +466,19 @@
30 dbusmenu_menuitem_property_set (mi,
31 "type",
32 "separator");
33+
34+ gint mode = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "gtk-separator-mode"));
35+
36+ // g_print ("mode == %d, previous_separator == %d\n", mode, previous_separator);
37+
38+ dbusmenu_menuitem_property_set_bool (mi,
39+ DBUSMENU_MENUITEM_PROP_VISIBLE,
40+ mode == SEPARATOR_MODE_SMART && !previous_separator);
41 }
42 else
43 {
44+ gboolean visible = FALSE;
45+
46 g_signal_connect (widget,
47 "accel-closures-changed",
48 G_CALLBACK (accel_changed),
49@@ -487,9 +504,14 @@
50 "label",
51 get_menu_label_text (widget));
52
53+ if (!g_object_get_data (G_OBJECT (widget), "gtk-empty-menu-item") && !GTK_IS_TEAROFF_MENU_ITEM (widget))
54+ {
55+ visible = gtk_widget_get_visible (widget);
56+ }
57+
58 dbusmenu_menuitem_property_set_bool (mi,
59 DBUSMENU_MENUITEM_PROP_VISIBLE,
60- gtk_widget_get_visible (widget));
61+ visible);
62
63 dbusmenu_menuitem_property_set_bool (mi,
64 DBUSMENU_MENUITEM_PROP_ENABLED,
65@@ -519,13 +541,23 @@
66 if (GTK_IS_CONTAINER (widget))
67 {
68 gboolean increment = GTK_IS_MENU_BAR (widget) || GTK_IS_MENU_ITEM (widget);
69- gboolean skip = FALSE;
70+ gboolean previous_separator = FALSE;
71
72 if (increment)
73 recurse->count++;
74
75 if (recurse->count > -1 && increment)
76 {
77+ /* If this is a separator, find out if we've already displayed a visible separator during
78+ * this run. GtkUIManager internally defines the following separator modes:
79+ *
80+ * SEPARATOR_MODE_SMART
81+ * SEPARATOR_MODE_VISIBLE
82+ * SEPARATOR_MODE_HIDDEN
83+ *
84+ * construct_dbusmenu_for_widget() will mark a smart separator as visible in a run of
85+ * separators unless it is following another smart separator anywhere in that run.
86+ */
87 if (GTK_IS_SEPARATOR_MENU_ITEM (widget))
88 {
89 if (recurse->stack[recurse->count] != NULL)
90@@ -535,14 +567,30 @@
91
92 if (g_strcmp0 (type, "separator") == 0)
93 {
94- skip = TRUE;
95+ /* Get the previous separator mode. */
96+ gint mode = recurse->mode[recurse->count];
97+
98+ if (mode == SEPARATOR_MODE_SMART)
99+ previous_separator = TRUE;
100 }
101 }
102 }
103
104- if (!gtk_widget_get_visible (widget))
105+ recurse->stack[recurse->count] = construct_dbusmenu_for_widget (widget, previous_separator);
106+
107+ if (GTK_IS_SEPARATOR_MENU_ITEM (widget))
108 {
109- skip = TRUE;
110+ /* If the previous separator was mode 1, let's pretend that this separator is also mode 1.
111+ * That means for the remainder of this run of separators, all will be marked as mode 1.
112+ */
113+ if (previous_separator)
114+ {
115+ recurse->mode[recurse->count] = SEPARATOR_MODE_SMART;
116+ }
117+ else
118+ {
119+ recurse->mode[recurse->count] = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "gtk-separator-mode"));
120+ }
121 }
122
123 if (!gtk_widget_get_visible (widget))
124@@ -551,22 +599,25 @@
125 "notify",
126 G_CALLBACK (menuitem_notify_cb),
127 recurse->context);
128- skip = TRUE;
129- }
130-
131- if (!skip)
132- {
133- recurse->stack[recurse->count] = construct_dbusmenu_for_widget (widget);
134-
135- if (recurse->count > 0)
136- {
137- if (recurse->count == 1)
138- dbusmenu_menuitem_child_append (recurse->stack[recurse->count - 1],
139- recurse->stack[recurse->count]);
140- else
141- dbusmenu_menuitem_child_prepend (recurse->stack[recurse->count - 1],
142- recurse->stack[recurse->count]);
143- }
144+ }
145+
146+ // g_print ("%d: %s %s\n", recurse->count, G_OBJECT_TYPE_NAME (widget), get_menu_label_text (widget));
147+
148+ if (GTK_IS_TEAROFF_MENU_ITEM (widget))
149+ {
150+ dbusmenu_menuitem_property_set_bool (recurse->stack[recurse->count],
151+ DBUSMENU_MENUITEM_PROP_VISIBLE,
152+ FALSE);
153+ }
154+
155+ if (recurse->count > 0)
156+ {
157+ if (recurse->count == 1)
158+ dbusmenu_menuitem_child_append (recurse->stack[recurse->count - 1],
159+ recurse->stack[recurse->count]);
160+ else
161+ dbusmenu_menuitem_child_prepend (recurse->stack[recurse->count - 1],
162+ recurse->stack[recurse->count]);
163 }
164 }
165

Subscribers

People subscribed via source and target branches