Merge lp:~ted/libappindicator/unity-parser into lp:libappindicator/13.10
- unity-parser
- Merge into trunk.13.10
Status: | Superseded |
---|---|
Proposed branch: | lp:~ted/libappindicator/unity-parser |
Merge into: | lp:libappindicator/13.10 |
Diff against target: |
818 lines (+333/-157) 8 files modified
configure.ac (+2/-2) debian/control (+2/-3) example/simple-client.c (+0/-2) src/app-indicator.c (+283/-84) src/app-indicator.h (+0/-4) src/notification-item.xml (+2/-0) tests/test-libappindicator.c (+35/-55) tests/test-simple-app.c (+9/-7) |
To merge this branch: | bzr merge lp:~ted/libappindicator/unity-parser |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Indicator Applet Developers | Pending | ||
Review via email: mp+162011@code.launchpad.net |
This proposal has been superseded by a proposal from 2013-06-09.
Commit message
Convert from DBusmenu to GMenuModel
Description of the change
Changing the backend of libappindicator to be based on GMenuModel instead of DBusmenu.
Pushing this up for review and people to start looking at, but if it lands the world will end. Okay, probably not that, but nothing will work as indicator-
PS Jenkins bot (ps-jenkins) wrote : | # |
Charles Kerr (charlesk) wrote : | # |
> Pushing this up for review and people to start looking at, but if it lands the world will end.
Some people just want to watch the world burn. APPROVE
- 278. By Ted Gould
-
Adding back the server property and returning a warning
- 279. By Ted Gould
-
Keep the menu property as DBusmenu so we can tell between the two
- 280. By Ted Gould
-
Add properties for the GMenuModels
- 281. By Ted Gould
-
Adding support for the properties in their current form.
- 282. By Ted Gould
-
Fixing some docs errors
- 283. By Ted Gould
-
Adds in a structure and an array so that we can start tracking action groups as a set
- 284. By Ted Gould
-
Putting the bus stuff in the action info structure
- 285. By Ted Gould
-
Switch over to using the ActionInfo array
- 286. By Ted Gould
-
Handling the debug property using boxed types
- 287. By Ted Gould
-
Upgrade to a pop culture reference
- 288. By Ted Gould
-
Make GTK doc happy
- 289. By Ted Gould
-
Blocking a silly warning that isn't useful. Remember this when commenting on the quality of the GLib API.
Ted Gould (ted) wrote : | # |
Okay, I think I'm happy with this now. Had to clean up some of the action groups stuff. But it should work in most cases now. Next rev we can add a way to put GMenu/GActionGroups in with supported functions. For now we just need to support the old API.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:289
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
Ted Gould (ted) wrote : | # |
Wanted to note here so no one else investigates that the reason Jenkins is failing is because Raring doesn't have the required dependencies. They are in Saucy and the job is on the list to be updated.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:289
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
- 289. By Ted Gould
-
Blocking a silly warning that isn't useful. Remember this when commenting on the quality of the GLib API.
- 288. By Ted Gould
-
Make GTK doc happy
- 287. By Ted Gould
-
Upgrade to a pop culture reference
- 286. By Ted Gould
-
Handling the debug property using boxed types
- 285. By Ted Gould
-
Switch over to using the ActionInfo array
- 284. By Ted Gould
-
Putting the bus stuff in the action info structure
- 283. By Ted Gould
-
Adds in a structure and an array so that we can start tracking action groups as a set
- 282. By Ted Gould
-
Fixing some docs errors
- 281. By Ted Gould
-
Adding support for the properties in their current form.
- 280. By Ted Gould
-
Add properties for the GMenuModels
Preview Diff
1 | === modified file 'configure.ac' |
2 | --- configure.ac 2013-01-29 17:50:13 +0000 |
3 | +++ configure.ac 2013-05-08 17:21:26 +0000 |
4 | @@ -58,7 +58,7 @@ |
5 | glib-2.0 >= $GLIB_REQUIRED_VERSION |
6 | gio-2.0 >= $GIO_REQUIRED_VERSION |
7 | indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION |
8 | - dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION) |
9 | + unity-gtk3-parser) |
10 | AC_DEFINE(HAVE_GTK3, 1, [whether gtk3 is available]) |
11 | ], |
12 | [test "x$with_gtk" = x2], |
13 | @@ -66,7 +66,7 @@ |
14 | glib-2.0 >= $GLIB_REQUIRED_VERSION |
15 | gio-2.0 >= $GIO_REQUIRED_VERSION |
16 | indicator-0.4 >= $INDICATOR_REQUIRED_VERSION |
17 | - dbusmenu-gtk-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION) |
18 | + unity-gtk2-parser) |
19 | ], |
20 | [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] |
21 | ) |
22 | |
23 | === modified file 'debian/control' |
24 | --- debian/control 2013-03-11 12:59:43 +0000 |
25 | +++ debian/control 2013-05-08 17:21:26 +0000 |
26 | @@ -26,9 +26,8 @@ |
27 | libdbus-glib-1-dev (>= 0.82), |
28 | libindicator-dev (>= 0.3.90), |
29 | libindicator3-dev (>= 0.3.90), |
30 | - libdbusmenu-glib-dev (>= 0.5.90), |
31 | - libdbusmenu-gtk-dev (>= 0.5.90), |
32 | - libdbusmenu-gtk3-dev (>= 0.5.90), |
33 | + libunity-gtk2-parser-dev, |
34 | + libunity-gtk3-parser-dev, |
35 | libgirepository1.0-dev, |
36 | gir1.2-glib-2.0, |
37 | gir1.2-gtk-2.0, |
38 | |
39 | === modified file 'example/simple-client.c' |
40 | --- example/simple-client.c 2012-01-29 03:38:55 +0000 |
41 | +++ example/simple-client.c 2013-05-08 17:21:26 +0000 |
42 | @@ -21,8 +21,6 @@ |
43 | */ |
44 | |
45 | #include "app-indicator.h" |
46 | -#include "libdbusmenu-glib/server.h" |
47 | -#include "libdbusmenu-glib/menuitem.h" |
48 | |
49 | GMainLoop * mainloop = NULL; |
50 | static gboolean active = TRUE; |
51 | |
52 | === modified file 'src/app-indicator.c' |
53 | --- src/app-indicator.c 2013-04-19 12:07:21 +0000 |
54 | +++ src/app-indicator.c 2013-05-08 17:21:26 +0000 |
55 | @@ -31,10 +31,7 @@ |
56 | #include "config.h" |
57 | #endif |
58 | |
59 | -#include <libdbusmenu-glib/menuitem.h> |
60 | -#include <libdbusmenu-glib/server.h> |
61 | -#include <libdbusmenu-gtk/client.h> |
62 | -#include <libdbusmenu-gtk/parser.h> |
63 | +#include <unity-gtk-parser.h> |
64 | |
65 | #include <libindicator/indicator-desktop-shortcuts.h> |
66 | |
67 | @@ -52,16 +49,8 @@ |
68 | |
69 | /** |
70 | * AppIndicatorPrivate: |
71 | + * |
72 | * All of the private data in an instance of an application indicator. |
73 | - * |
74 | - * Private Fields |
75 | - * @id: The ID of the indicator. Maps to AppIndicator:id. |
76 | - * @category: Which category the indicator is. Maps to AppIndicator:category. |
77 | - * @status: The status of the indicator. Maps to AppIndicator:status. |
78 | - * @icon_name: The name of the icon to use. Maps to AppIndicator:icon-name. |
79 | - * @attention_icon_name: The name of the attention icon to use. Maps to AppIndicator:attention-icon-name. |
80 | - * @menu: The menu for this indicator. Maps to AppIndicator:menu |
81 | - * @watcher_proxy: The proxy connection to the watcher we're connected to. If we're not connected to one this will be %NULL. |
82 | */ |
83 | struct _AppIndicatorPrivate { |
84 | /*< Private >*/ |
85 | @@ -73,7 +62,6 @@ |
86 | gchar *icon_name; |
87 | gchar *attention_icon_name; |
88 | gchar *icon_theme_path; |
89 | - DbusmenuServer *menuservice; |
90 | GtkWidget *menu; |
91 | GtkWidget *sec_activate_target; |
92 | gboolean sec_activate_enabled; |
93 | @@ -88,6 +76,12 @@ |
94 | GtkStatusIcon * status_icon; |
95 | gint fallback_timer; |
96 | |
97 | + /* Menu Stuff */ |
98 | + GMenuModel * menu_model; |
99 | + guint menu_model_export; |
100 | + gchar * menu_shell_path; |
101 | + GArray * menu_groups; |
102 | + |
103 | /* Fun stuff */ |
104 | GDBusProxy *watcher_proxy; |
105 | GDBusConnection *connection; |
106 | @@ -98,6 +92,16 @@ |
107 | IndicatorDesktopShortcuts * shorties; |
108 | }; |
109 | |
110 | +typedef struct _ActionInfo ActionInfo; |
111 | +struct _ActionInfo { |
112 | + gchar * prefix; |
113 | + gchar * path; |
114 | + GActionGroup * group; |
115 | + |
116 | + GDBusConnection * bus; |
117 | + guint export; |
118 | +}; |
119 | + |
120 | /* Signals Stuff */ |
121 | enum { |
122 | NEW_ICON, |
123 | @@ -129,6 +133,8 @@ |
124 | PROP_LABEL_GUIDE, |
125 | PROP_ORDERING_INDEX, |
126 | PROP_DBUS_MENU_SERVER, |
127 | + PROP_MENU_MODEL, |
128 | + PROP_ACTION_GROUPS, |
129 | PROP_TITLE |
130 | }; |
131 | |
132 | @@ -147,6 +153,8 @@ |
133 | #define PROP_ORDERING_INDEX_S "ordering-index" |
134 | #define PROP_DBUS_MENU_SERVER_S "dbus-menu-server" |
135 | #define PROP_TITLE_S "title" |
136 | +#define PROP_MENU_MODEL_S "menu-model" |
137 | +#define PROP_ACTION_GROUPS_S "action-groups" |
138 | |
139 | /* Private macro, shhhh! */ |
140 | #define APP_INDICATOR_GET_PRIVATE(o) \ |
141 | @@ -194,6 +202,10 @@ |
142 | static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data); |
143 | static void bus_creation (GObject * obj, GAsyncResult * res, gpointer user_data); |
144 | static void bus_watcher_ready (GObject * obj, GAsyncResult * res, gpointer user_data); |
145 | +static void setup_dbusmenu (AppIndicator *self); |
146 | +static void unexport_menu (AppIndicator *self); |
147 | +static void export_me_maybe (AppIndicator *self); |
148 | +static void action_info_clear (gpointer datain); |
149 | |
150 | static const GDBusInterfaceVTable item_interface_table = { |
151 | method_call: bus_method_call, |
152 | @@ -399,7 +411,6 @@ |
153 | "A way to override the default ordering of the applications by providing a very specific idea of where this entry should be placed.", |
154 | 0, G_MAXUINT32, 0, |
155 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
156 | - |
157 | /** |
158 | * AppIndicator:dbus-menu-server: |
159 | * |
160 | @@ -411,7 +422,7 @@ |
161 | g_param_spec_object (PROP_DBUS_MENU_SERVER_S, |
162 | "The internal DBusmenu Server", |
163 | "DBusmenu server which is available for testing the application indicators.", |
164 | - DBUSMENU_TYPE_SERVER, |
165 | + G_TYPE_OBJECT, |
166 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
167 | /** |
168 | * AppIndicator:title: |
169 | @@ -429,6 +440,34 @@ |
170 | NULL, |
171 | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
172 | |
173 | + /** |
174 | + * AppIndicator:menu-model: |
175 | + * |
176 | + * The built menu model. This is only used for testing and should |
177 | + * not be considered stable. |
178 | + */ |
179 | + g_object_class_install_property(object_class, |
180 | + PROP_MENU_MODEL, |
181 | + g_param_spec_object (PROP_MENU_MODEL_S, |
182 | + "Internal Menu Model", |
183 | + "TESTING ONLY: Property to get the menu model", |
184 | + G_TYPE_MENU_MODEL, |
185 | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
186 | + |
187 | + /** |
188 | + * AppIndicator:action-groups: |
189 | + * |
190 | + * The built action group. This is only used for testing and should |
191 | + * not be considered stable. |
192 | + */ |
193 | + g_object_class_install_property(object_class, |
194 | + PROP_ACTION_GROUPS, |
195 | + g_param_spec_boxed (PROP_ACTION_GROUPS_S, |
196 | + "Internal Action Group", |
197 | + "TESTING ONLY: Property to get the action group", |
198 | + G_TYPE_ARRAY, |
199 | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
200 | + |
201 | /* Signals */ |
202 | |
203 | /** |
204 | @@ -479,7 +518,7 @@ |
205 | * AppIndicator::new-label: |
206 | * @arg0: The #AppIndicator object |
207 | * @arg1: The string for the label |
208 | - * @arg1: The string for the guide |
209 | + * @arg2: The string for the guide |
210 | * |
211 | * Emitted when either #AppIndicator:label or #AppIndicator:label-guide are |
212 | * changed. |
213 | @@ -591,7 +630,7 @@ |
214 | priv->attention_icon_name = NULL; |
215 | priv->icon_theme_path = NULL; |
216 | priv->menu = NULL; |
217 | - priv->menuservice = NULL; |
218 | + priv->menu_shell_path = NULL; |
219 | priv->ordering_index = 0; |
220 | priv->title = NULL; |
221 | priv->label = NULL; |
222 | @@ -611,6 +650,9 @@ |
223 | priv->sec_activate_target = NULL; |
224 | priv->sec_activate_enabled = FALSE; |
225 | |
226 | + priv->menu_groups = g_array_new(FALSE /* zero term */, FALSE /* clear */, sizeof(ActionInfo)); |
227 | + g_array_set_clear_func(priv->menu_groups, action_info_clear); |
228 | + |
229 | self->priv = priv; |
230 | |
231 | /* Start getting the session bus */ |
232 | @@ -663,8 +705,12 @@ |
233 | priv->menu = NULL; |
234 | } |
235 | |
236 | - if (priv->menuservice != NULL) { |
237 | - g_object_unref (priv->menuservice); |
238 | + unexport_menu(self); |
239 | + |
240 | + g_clear_object(&priv->menu_model); |
241 | + |
242 | + if (priv->menu_groups->len > 0) { |
243 | + g_array_remove_range(priv->menu_groups, 0, priv->menu_groups->len); |
244 | } |
245 | |
246 | if (priv->watcher_proxy != NULL) { |
247 | @@ -765,10 +811,37 @@ |
248 | priv->path = NULL; |
249 | } |
250 | |
251 | + g_clear_pointer(&priv->menu_shell_path, g_free); |
252 | + |
253 | + if (priv->menu_groups != NULL) { |
254 | + g_array_free(priv->menu_groups, TRUE /* destroy segment */); |
255 | + priv->menu_groups = NULL; |
256 | + } |
257 | + |
258 | G_OBJECT_CLASS (app_indicator_parent_class)->finalize (object); |
259 | return; |
260 | } |
261 | |
262 | +/* Cleans up an action info struct */ |
263 | +static void |
264 | +action_info_clear (gpointer datain) |
265 | +{ |
266 | + ActionInfo * ainfo = (ActionInfo *)datain; |
267 | + |
268 | + g_clear_pointer(&ainfo->prefix, g_free); |
269 | + g_clear_pointer(&ainfo->path, g_free); |
270 | + g_clear_object(&ainfo->group); |
271 | + |
272 | + if (ainfo->export != 0) { |
273 | + g_dbus_connection_unexport_action_group(ainfo->bus, ainfo->export); |
274 | + ainfo->export = 0; |
275 | + } |
276 | + |
277 | + g_clear_object(&ainfo->bus); |
278 | + |
279 | + return; |
280 | +} |
281 | + |
282 | #define WARN_BAD_TYPE(prop, value) g_warning("Can not work with property '%s' with value of type '%s'.", prop, G_VALUE_TYPE_NAME(value)) |
283 | |
284 | /* Set some properties */ |
285 | @@ -926,10 +999,28 @@ |
286 | break; |
287 | |
288 | case PROP_DBUS_MENU_SERVER: |
289 | - g_clear_object (&priv->menuservice); |
290 | - priv->menuservice = DBUSMENU_SERVER (g_value_dup_object(value)); |
291 | - break; |
292 | - |
293 | + g_warning("DBus Menu Server is a testing parameter. Why are you using it? Please stop."); |
294 | + break; |
295 | + |
296 | + case PROP_MENU_MODEL: |
297 | + unexport_menu(self); |
298 | + |
299 | + g_clear_object(&priv->menu_model); |
300 | + priv->menu_model = g_value_dup_object(value); |
301 | + |
302 | + export_me_maybe(self); |
303 | + break; |
304 | + case PROP_ACTION_GROUPS: |
305 | + if (priv->menu_groups != NULL) { |
306 | + g_array_free(priv->menu_groups, TRUE /* destroy segment */); |
307 | + priv->menu_groups = NULL; |
308 | + } |
309 | + |
310 | + priv->menu_groups = g_value_get_boxed(value); |
311 | + g_array_ref(priv->menu_groups); |
312 | + |
313 | + export_me_maybe(self); |
314 | + break; |
315 | default: |
316 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
317 | break; |
318 | @@ -1009,13 +1100,22 @@ |
319 | break; |
320 | |
321 | case PROP_DBUS_MENU_SERVER: |
322 | - g_value_set_object(value, priv->menuservice); |
323 | + g_warning("DBus Menu Server is a testing parameter. Why are you using it? Please stop."); |
324 | + g_value_set_object(value, NULL); |
325 | break; |
326 | |
327 | case PROP_TITLE: |
328 | g_value_set_string(value, priv->title); |
329 | break; |
330 | |
331 | + case PROP_MENU_MODEL: |
332 | + g_value_set_object(value, priv->menu_model); |
333 | + break; |
334 | + |
335 | + case PROP_ACTION_GROUPS: |
336 | + g_value_set_boxed(value, priv->menu_groups); |
337 | + break; |
338 | + |
339 | default: |
340 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
341 | break; |
342 | @@ -1138,16 +1238,7 @@ |
343 | } else if (g_strcmp0(property, "IconThemePath") == 0) { |
344 | return g_variant_new_string(priv->icon_theme_path ? priv->icon_theme_path : ""); |
345 | } else if (g_strcmp0(property, "Menu") == 0) { |
346 | - if (priv->menuservice != NULL) { |
347 | - GValue strval = { 0 }; |
348 | - g_value_init(&strval, G_TYPE_STRING); |
349 | - g_object_get_property (G_OBJECT (priv->menuservice), DBUSMENU_SERVER_PROP_DBUS_OBJECT, &strval); |
350 | - GVariant * var = g_variant_new("o", g_value_get_string(&strval)); |
351 | - g_value_unset(&strval); |
352 | - return var; |
353 | - } else { |
354 | - return g_variant_new("o", "/"); |
355 | - } |
356 | + return g_variant_new("o", "/"); |
357 | } else if (g_strcmp0(property, "XAyatanaLabel") == 0) { |
358 | return g_variant_new_string(priv->label ? priv->label : ""); |
359 | } else if (g_strcmp0(property, "XAyatanaLabelGuide") == 0) { |
360 | @@ -1158,6 +1249,31 @@ |
361 | return g_variant_new_string(priv->accessible_desc ? priv->accessible_desc : ""); |
362 | } else if (g_strcmp0(property, "AttentionAccessibleDesc") == 0) { |
363 | return g_variant_new_string(priv->att_accessible_desc ? priv->att_accessible_desc : ""); |
364 | + } else if (g_strcmp0(property, "XCanonicalMenuModel") == 0) { |
365 | + if (priv->menu_shell_path != NULL) { |
366 | + return g_variant_new_object_path(priv->menu_shell_path); |
367 | + } else { |
368 | + return g_variant_new_object_path("/"); |
369 | + } |
370 | + } else if (g_strcmp0(property, "XCanonicalActionGroups") == 0) { |
371 | + if (priv->menu_groups->len != 0) { |
372 | + GVariantBuilder array; |
373 | + g_variant_builder_init(&array, G_VARIANT_TYPE_ARRAY); |
374 | + |
375 | + int i; |
376 | + for (i = 0; i < priv->menu_groups->len; i++) { |
377 | + ActionInfo * ainfo = &g_array_index(priv->menu_groups, ActionInfo, i); |
378 | + |
379 | + g_variant_builder_open(&array, G_VARIANT_TYPE_TUPLE); |
380 | + g_variant_builder_add_value(&array, g_variant_new_string(ainfo->prefix)); |
381 | + g_variant_builder_add_value(&array, g_variant_new_object_path(ainfo->path)); |
382 | + g_variant_builder_close(&array); |
383 | + } |
384 | + |
385 | + return g_variant_builder_end(&array); |
386 | + } else { |
387 | + return g_variant_new_array(G_VARIANT_TYPE("(so)"), NULL, 0); |
388 | + } |
389 | } |
390 | |
391 | *error = g_error_new(0, 0, "Unknown property: %s", property); |
392 | @@ -1261,6 +1377,8 @@ |
393 | } |
394 | } |
395 | |
396 | + export_me_maybe(self); |
397 | + |
398 | /* NOTE: It's really important the order here. We make sure to *publish* |
399 | the object on the bus and *then* get the proxy. The reason is that we |
400 | want to ensure all the filters are setup before talking to the watcher |
401 | @@ -1746,6 +1864,79 @@ |
402 | self->priv->sec_activate_enabled = widget_is_menu_child(self, menuitem); |
403 | } |
404 | |
405 | +/* Unexport the menu, doesn't unref objects */ |
406 | +static void |
407 | +unexport_menu (AppIndicator *self) |
408 | +{ |
409 | + AppIndicatorPrivate *priv = self->priv; |
410 | + |
411 | + if (priv->connection == NULL) { |
412 | + return; |
413 | + } |
414 | + |
415 | + if (priv->menu_model_export != 0) { |
416 | + g_dbus_connection_unexport_menu_model(priv->connection, priv->menu_model_export); |
417 | + priv->menu_model_export = 0; |
418 | + } |
419 | + |
420 | + if (priv->menu_groups->len > 0) { |
421 | + g_array_remove_range(priv->menu_groups, 0, priv->menu_groups->len); |
422 | + } |
423 | + |
424 | + g_clear_pointer(&priv->menu_shell_path, g_free); |
425 | + |
426 | + return; |
427 | +} |
428 | + |
429 | +/* We just met, and I know this is crazy, but export me maybe? */ |
430 | +/* Export the menu if we've got everything we need */ |
431 | +static void |
432 | +export_me_maybe (AppIndicator *self) |
433 | +{ |
434 | + AppIndicatorPrivate *priv = self->priv; |
435 | + |
436 | + if (priv->connection == NULL) { |
437 | + return; |
438 | + } |
439 | + |
440 | + if (priv->menu_model == NULL) { |
441 | + return; |
442 | + } |
443 | + |
444 | + if (priv->menu_groups->len == 0) { |
445 | + return; |
446 | + } |
447 | + |
448 | + if (priv->menu_model_export != 0) { |
449 | + return; |
450 | + } |
451 | + |
452 | + GError * error = NULL; |
453 | + int i; |
454 | + for (i = 0; i < priv->menu_groups->len; i++) { |
455 | + ActionInfo * ainfo = &g_array_index(priv->menu_groups, ActionInfo, i); |
456 | + |
457 | + ainfo->bus = g_object_ref(priv->connection); |
458 | + |
459 | + ainfo->export = g_dbus_connection_export_action_group(ainfo->bus, ainfo->path, ainfo->group, &error); |
460 | + |
461 | + if (error != NULL) { |
462 | + g_warning("Unable to export action group as '%s': %s", ainfo->path, error->message); |
463 | + g_error_free(error); |
464 | + error = NULL; |
465 | + } |
466 | + } |
467 | + |
468 | + priv->menu_model_export = g_dbus_connection_export_menu_model(priv->connection, priv->menu_shell_path, priv->menu_model, NULL); |
469 | + |
470 | + if (error != NULL) { |
471 | + g_warning("Unable to export menu model as '%s': %s", priv->menu_shell_path, error->message); |
472 | + g_error_free(error); |
473 | + error = NULL; |
474 | + } |
475 | + |
476 | + return; |
477 | +} |
478 | |
479 | /* ************************* */ |
480 | /* Public Functions */ |
481 | @@ -2072,25 +2263,26 @@ |
482 | setup_dbusmenu (AppIndicator *self) |
483 | { |
484 | AppIndicatorPrivate *priv; |
485 | - DbusmenuMenuitem *root = NULL; |
486 | - |
487 | priv = self->priv; |
488 | |
489 | + unexport_menu(self); |
490 | + |
491 | + g_clear_object(&priv->menu_model); |
492 | + |
493 | if (priv->menu) { |
494 | - root = dbusmenu_gtk_parse_menu_structure(priv->menu); |
495 | - } |
496 | - |
497 | - if (priv->menuservice == NULL) { |
498 | - gchar * path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s/Menu", priv->clean_id); |
499 | - priv->menuservice = dbusmenu_server_new (path); |
500 | - g_free(path); |
501 | - } |
502 | - |
503 | - dbusmenu_server_set_root (priv->menuservice, root); |
504 | - |
505 | - /* Drop our local ref as set_root should get it's own. */ |
506 | - if (root != NULL) { |
507 | - g_object_unref(root); |
508 | + ActionInfo ainfo; |
509 | + |
510 | + priv->menu_model = G_MENU_MODEL(unity_gtk_menu_shell_new(GTK_MENU_SHELL(priv->menu))); |
511 | + priv->menu_shell_path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s/Menu", priv->clean_id); |
512 | + |
513 | + ainfo.group = G_ACTION_GROUP(unity_gtk_action_group_new(NULL)); |
514 | + ainfo.prefix = g_strdup("unity"); |
515 | + ainfo.path = g_strdup(priv->menu_shell_path); |
516 | + g_array_append_val(priv->menu_groups, ainfo); |
517 | + |
518 | + unity_gtk_action_group_connect_shell(UNITY_GTK_ACTION_GROUP(ainfo.group), UNITY_GTK_MENU_SHELL(priv->menu_model)); |
519 | + |
520 | + export_me_maybe(self); |
521 | } |
522 | |
523 | return; |
524 | @@ -2463,14 +2655,13 @@ |
525 | return GTK_WIDGET(self->priv->sec_activate_target); |
526 | } |
527 | |
528 | -#define APP_INDICATOR_SHORTY_NICK "app-indicator-shorty-nick" |
529 | - |
530 | /* Callback when an item from the desktop shortcuts gets |
531 | called. */ |
532 | static void |
533 | -shorty_activated_cb (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data) |
534 | +shorty_activated_cb (GSimpleAction * action, GVariant * param, gpointer user_data) |
535 | { |
536 | - gchar * nick = g_object_get_data(G_OBJECT(mi), APP_INDICATOR_SHORTY_NICK); |
537 | + gchar * nick = NULL; |
538 | + g_object_get(G_OBJECT(action), "name", &nick, NULL); |
539 | g_return_if_fail(nick != NULL); |
540 | |
541 | g_return_if_fail(IS_APP_INDICATOR(user_data)); |
542 | @@ -2500,45 +2691,53 @@ |
543 | AppIndicatorPrivate *priv = self->priv; |
544 | |
545 | /* Build a new shortcuts object */ |
546 | - if (priv->shorties != NULL) { |
547 | - g_object_unref(priv->shorties); |
548 | - priv->shorties = NULL; |
549 | - } |
550 | + g_clear_object(&priv->shorties); |
551 | priv->shorties = indicator_desktop_shortcuts_new(desktop_file, desktop_profile); |
552 | g_return_if_fail(priv->shorties != NULL); |
553 | |
554 | + /* Remove the exported menu */ |
555 | + unexport_menu(self); |
556 | + |
557 | + g_clear_object(&priv->menu_model); |
558 | + |
559 | + /* Get the 'nicks' */ |
560 | const gchar ** nicks = indicator_desktop_shortcuts_get_nicks(priv->shorties); |
561 | + |
562 | + if (nicks[0] == NULL) { |
563 | + g_warning("Desktop file '%s' doesn't contain any usable actions", desktop_file); |
564 | + return; |
565 | + } |
566 | + |
567 | + /* Build new menus and action groups */ |
568 | + GMenu * menu = g_menu_new(); |
569 | + priv->menu_model = G_MENU_MODEL(menu); |
570 | + priv->menu_shell_path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s/Menu", priv->clean_id); |
571 | + |
572 | + ActionInfo ainfo; |
573 | + GSimpleActionGroup * actions = g_simple_action_group_new(); |
574 | + ainfo.group = G_ACTION_GROUP(actions); |
575 | + ainfo.prefix = g_strdup(""); |
576 | + ainfo.path = g_strdup(priv->menu_shell_path); |
577 | + g_array_append_val(priv->menu_groups, ainfo); |
578 | + |
579 | int nick_num; |
580 | - |
581 | - /* Place the items on a dbusmenu */ |
582 | - DbusmenuMenuitem * root = dbusmenu_menuitem_new(); |
583 | - |
584 | for (nick_num = 0; nicks[nick_num] != NULL; nick_num++) { |
585 | - DbusmenuMenuitem * item = dbusmenu_menuitem_new(); |
586 | - g_object_set_data(G_OBJECT(item), APP_INDICATOR_SHORTY_NICK, (gpointer)nicks[nick_num]); |
587 | + GSimpleAction * action = g_simple_action_new(nicks[nick_num], NULL); |
588 | + g_signal_connect(action, "activate", G_CALLBACK(shorty_activated_cb), self); |
589 | |
590 | gchar * name = indicator_desktop_shortcuts_nick_get_name(priv->shorties, nicks[nick_num]); |
591 | - dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, name); |
592 | + GMenuItem * item = g_menu_item_new(name, nicks[nick_num]); |
593 | g_free(name); |
594 | |
595 | - g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(shorty_activated_cb), self); |
596 | - |
597 | - dbusmenu_menuitem_child_append(root, item); |
598 | - } |
599 | - |
600 | - /* Swap it if needed */ |
601 | - if (priv->menuservice == NULL) { |
602 | - gchar * path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s/Menu", priv->clean_id); |
603 | - priv->menuservice = dbusmenu_server_new (path); |
604 | - g_free(path); |
605 | - } |
606 | - |
607 | - dbusmenu_server_set_root (priv->menuservice, root); |
608 | - |
609 | - if (priv->menu != NULL) { |
610 | - g_object_unref(G_OBJECT(priv->menu)); |
611 | - priv->menu = NULL; |
612 | - } |
613 | + g_simple_action_group_insert(actions, G_ACTION(action)); |
614 | + g_menu_append_item(menu, item); |
615 | + |
616 | + g_object_unref(action); |
617 | + g_object_unref(item); |
618 | + } |
619 | + |
620 | + /* Export the menu and action group */ |
621 | + export_me_maybe(self); |
622 | |
623 | return; |
624 | } |
625 | |
626 | === modified file 'src/app-indicator.h' |
627 | --- src/app-indicator.h 2012-02-03 20:37:56 +0000 |
628 | +++ src/app-indicator.h 2013-05-08 17:21:26 +0000 |
629 | @@ -238,10 +238,6 @@ |
630 | * unique status in the panel for an application. In general, applications |
631 | * should try to fit in the other indicators that are available on the |
632 | * panel before using this. But, sometimes it is necissary. |
633 | - * |
634 | - * Private fields |
635 | - * @parent: Parent object. |
636 | - * @priv: Internal data. |
637 | */ |
638 | struct _AppIndicator { |
639 | GObject parent; |
640 | |
641 | === modified file 'src/notification-item.xml' |
642 | --- src/notification-item.xml 2012-02-03 20:37:56 +0000 |
643 | +++ src/notification-item.xml 2013-05-08 17:21:26 +0000 |
644 | @@ -18,6 +18,8 @@ |
645 | <property name="XAyatanaLabel" type="s" access="read" /> |
646 | <property name="XAyatanaLabelGuide" type="s" access="read" /> |
647 | <property name="XAyatanaOrderingIndex" type="u" access="read" /> |
648 | + <property name="XCanonicalMenuModel" type="o" access="read" /> |
649 | + <property name="XCanonicalActionGroups" type="a(so)" access="read" /> |
650 | |
651 | <!-- Methods --> |
652 | <method name="Scroll"> |
653 | |
654 | === modified file 'tests/test-libappindicator.c' |
655 | --- tests/test-libappindicator.c 2013-01-10 22:18:55 +0000 |
656 | +++ tests/test-libappindicator.c 2013-05-08 17:21:26 +0000 |
657 | @@ -22,12 +22,10 @@ |
658 | |
659 | #include <glib.h> |
660 | #include <glib-object.h> |
661 | +#include <gio/gio.h> |
662 | |
663 | #include <app-indicator.h> |
664 | |
665 | -#include <libdbusmenu-glib/menuitem.h> |
666 | -#include <libdbusmenu-glib/server.h> |
667 | - |
668 | static gboolean |
669 | allow_warnings (const gchar *log_domain, GLogLevelFlags log_level, |
670 | const gchar *message, gpointer user_data) |
671 | @@ -270,26 +268,26 @@ |
672 | |
673 | g_assert(app_indicator_get_menu(ci) != NULL); |
674 | |
675 | - GValue serverval = {0}; |
676 | - g_value_init(&serverval, DBUSMENU_TYPE_SERVER); |
677 | - g_object_get_property(G_OBJECT(ci), "dbus-menu-server", &serverval); |
678 | - |
679 | - DbusmenuServer * server = DBUSMENU_SERVER(g_value_get_object(&serverval)); |
680 | - g_assert(server != NULL); |
681 | - |
682 | - GValue rootval = {0}; |
683 | - g_value_init(&rootval, DBUSMENU_TYPE_MENUITEM); |
684 | - g_object_get_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_ROOT_NODE, &rootval); |
685 | - DbusmenuMenuitem * root = DBUSMENU_MENUITEM(g_value_get_object(&rootval)); |
686 | - g_assert(root != NULL); |
687 | - |
688 | - GList * children = dbusmenu_menuitem_get_children(root); |
689 | - g_assert(children != NULL); |
690 | - g_assert(g_list_length(children) == 1); |
691 | - |
692 | - const gchar * label = dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(children->data), DBUSMENU_MENUITEM_PROP_LABEL); |
693 | + GValue modelval = {0}; |
694 | + g_value_init(&modelval, G_TYPE_MENU_MODEL); |
695 | + g_object_get_property(G_OBJECT(ci), "menu-model", &modelval); |
696 | + |
697 | + GMenuModel * model = G_MENU_MODEL(g_value_get_object(&modelval)); |
698 | + g_assert(model != NULL); |
699 | + |
700 | + g_assert_cmpint(g_menu_model_get_n_items(model), ==, 1); |
701 | + |
702 | + GMenuModel * section = g_menu_model_get_item_link(model, 0, G_MENU_LINK_SECTION); |
703 | + g_assert(section != NULL); |
704 | + |
705 | + g_assert_cmpint(g_menu_model_get_n_items(section), ==, 1); |
706 | + |
707 | + GVariant * label = g_menu_model_get_item_attribute_value(section, 0, G_MENU_ATTRIBUTE_LABEL, G_VARIANT_TYPE_STRING); |
708 | g_assert(label != NULL); |
709 | - g_assert(g_strcmp0(label, "Test Label") == 0); |
710 | + g_assert(g_strcmp0("Test Label", g_variant_get_string(label, NULL)) == 0); |
711 | + |
712 | + g_variant_unref(label); |
713 | + g_object_unref(model); |
714 | |
715 | /* Interesting, eh? We need this because we send out events on the bus |
716 | but they don't come back until the idle is run. So we need those |
717 | @@ -388,24 +386,15 @@ |
718 | |
719 | app_indicator_build_menu_from_desktop(ci, SRCDIR "/test-libappindicator.desktop", "Test Program"); |
720 | |
721 | - GValue serverval = {0}; |
722 | - g_value_init(&serverval, DBUSMENU_TYPE_SERVER); |
723 | - g_object_get_property(G_OBJECT(ci), "dbus-menu-server", &serverval); |
724 | - |
725 | - DbusmenuServer * server = DBUSMENU_SERVER(g_value_get_object(&serverval)); |
726 | - g_assert(server != NULL); |
727 | - |
728 | - GValue rootval = {0}; |
729 | - g_value_init(&rootval, DBUSMENU_TYPE_MENUITEM); |
730 | - g_object_get_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_ROOT_NODE, &rootval); |
731 | - DbusmenuMenuitem * root = DBUSMENU_MENUITEM(g_value_get_object(&rootval)); |
732 | - g_assert(root != NULL); |
733 | - |
734 | - GList * children = dbusmenu_menuitem_get_children(root); |
735 | - g_assert(children != NULL); |
736 | - g_assert(g_list_length(children) == 3); |
737 | - |
738 | - |
739 | + GValue modelval = {0}; |
740 | + g_value_init(&modelval, G_TYPE_MENU_MODEL); |
741 | + g_object_get_property(G_OBJECT(ci), "menu-model", &modelval); |
742 | + |
743 | + GMenuModel * model = G_MENU_MODEL(g_value_get_object(&modelval)); |
744 | + g_assert(model != NULL); |
745 | + |
746 | + g_assert(g_menu_model_get_n_items(model) == 3); |
747 | + g_object_unref(model); |
748 | |
749 | g_object_unref(G_OBJECT(ci)); |
750 | return; |
751 | @@ -426,21 +415,12 @@ |
752 | |
753 | app_indicator_build_menu_from_desktop(ci, SRCDIR "/test-libappindicator.desktop", "Not Test Program"); |
754 | |
755 | - GValue serverval = {0}; |
756 | - g_value_init(&serverval, DBUSMENU_TYPE_SERVER); |
757 | - g_object_get_property(G_OBJECT(ci), "dbus-menu-server", &serverval); |
758 | - |
759 | - DbusmenuServer * server = DBUSMENU_SERVER(g_value_get_object(&serverval)); |
760 | - g_assert(server != NULL); |
761 | - |
762 | - GValue rootval = {0}; |
763 | - g_value_init(&rootval, DBUSMENU_TYPE_MENUITEM); |
764 | - g_object_get_property(G_OBJECT(server), DBUSMENU_SERVER_PROP_ROOT_NODE, &rootval); |
765 | - DbusmenuMenuitem * root = DBUSMENU_MENUITEM(g_value_get_object(&rootval)); |
766 | - g_assert(root != NULL); |
767 | - |
768 | - GList * children = dbusmenu_menuitem_get_children(root); |
769 | - g_assert(g_list_length(children) == 0); |
770 | + GValue modelval = {0}; |
771 | + g_value_init(&modelval, G_TYPE_MENU_MODEL); |
772 | + g_object_get_property(G_OBJECT(ci), "menu-model", &modelval); |
773 | + |
774 | + GMenuModel * model = G_MENU_MODEL(g_value_get_object(&modelval)); |
775 | + g_assert(model == NULL); |
776 | |
777 | g_object_unref(G_OBJECT(ci)); |
778 | return; |
779 | |
780 | === modified file 'tests/test-simple-app.c' |
781 | --- tests/test-simple-app.c 2013-01-16 19:53:52 +0000 |
782 | +++ tests/test-simple-app.c 2013-05-08 17:21:26 +0000 |
783 | @@ -20,10 +20,8 @@ |
784 | */ |
785 | |
786 | |
787 | -#include <dbus/dbus-glib.h> |
788 | -#include <dbus/dbus-glib-lowlevel.h> |
789 | #include <glib.h> |
790 | -#include <libdbusmenu-glib/server.h> |
791 | +#include <gio/gio.h> |
792 | #include <app-indicator.h> |
793 | |
794 | static GMainLoop * mainloop = NULL; |
795 | @@ -31,15 +29,19 @@ |
796 | int |
797 | main (int argc, char ** argv) |
798 | { |
799 | - DbusmenuServer * dms = dbusmenu_server_new("/menu"); |
800 | - DbusmenuMenuitem * dmi = dbusmenu_menuitem_new(); |
801 | - dbusmenu_menuitem_property_set(dmi, "label", "Bob"); |
802 | + GMenu * menu = g_menu_new(); |
803 | + g_menu_append(menu, "Bob", "action"); |
804 | + |
805 | + GSimpleActionGroup * actions = g_simple_action_group_new(); |
806 | + GSimpleAction * action = g_simple_action_new("action", NULL); |
807 | + g_simple_action_group_insert(actions, G_ACTION(action)); |
808 | |
809 | AppIndicator * ci = APP_INDICATOR(g_object_new(APP_INDICATOR_TYPE, |
810 | "id", "test-application", |
811 | "status-enum", APP_INDICATOR_STATUS_ACTIVE, |
812 | "icon-name", "system-shutdown", |
813 | - "menu-object", dms, |
814 | + "menu-model", menu, |
815 | + "action-group", actions, |
816 | NULL)); |
817 | |
818 | mainloop = g_main_loop_new(NULL, FALSE); |
FAILED: Continuous integration, rev:277 jenkins. qa.ubuntu. com/job/ libappindicator -ci/8/ jenkins. qa.ubuntu. com/job/ libappindicator -raring- amd64-ci/ 9/console
http://
Executed test runs:
FAILURE: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ libappindicator -ci/8/rebuild
http://