Merge lp:~3v1n0/libappindicator/incons-paths-on-snap into lp:libappindicator/16.10

Proposed by Marco Trevisan (Treviño) on 2016-11-21
Status: Merged
Approved by: Andrea Azzarone on 2016-11-30
Approved revision: 288
Merged at revision: 277
Proposed branch: lp:~3v1n0/libappindicator/incons-paths-on-snap
Merge into: lp:libappindicator/16.10
Diff against target: 353 lines (+124/-14)
5 files modified
configure.ac (+1/-1)
debian/control (+1/-0)
debian/rules (+0/-2)
example/simple-client-vala.vala (+1/-1)
src/app-indicator.c (+121/-10)
To merge this branch: bzr merge lp:~3v1n0/libappindicator/incons-paths-on-snap
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) 2016-11-21 Approve on 2016-11-30
unity-api-1-bot continuous-integration Needs Fixing on 2016-11-29
Review via email: mp+311424@code.launchpad.net

Commit message

AppIndicator: fix icon and theme paths when running in $SNAP environment

Prepend $SNAP path to icons and theme paths when running in a sandboxed
environment, this allows to run app indicators without caring about the fact
they've been designed or compiled to run in a snap world or not.

Description of the change

See gtk2/gtk3 examples using this at https://github.com/3v1n0/indicators-examples-snaps

To post a comment you must log in.
Andrea Azzarone (azzar1) wrote :

LGTM.

review: Approve
Marco Trevisan (Treviño) (3v1n0) wrote :

Actually I've noticed that this is not correct when the developer uses an hardcoded path suc has /snap/$SNAP_NAME/current.

So it needs some tuning.

288. By Marco Trevisan (Treviño) on 2016-11-29

app-indicator: get real path on snap when trying to transform it

So when pointing to /snap/<name>/current will be automatically translated
to /snap/<name>/<current_revision>/...

Marco Trevisan (Treviño) (3v1n0) wrote :

Done this part too...

unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:288
https://jenkins.canonical.com/unity-api-1/job/lp-libappindicator-ci/7/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/1208/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1215
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1000
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1000/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1000
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1000/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1000/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/1000/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/1000/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1000
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1000/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-libappindicator-ci/7/rebuild

review: Needs Fixing (continuous-integration)
Andrea Azzarone (azzar1) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2013-01-29 17:50:13 +0000
3+++ configure.ac 2016-11-29 17:27:34 +0000
4@@ -121,7 +121,7 @@
5 RUNTIME=mono
6 fi
7
8- AC_PATH_PROG(CSC, gmcs, no)
9+ AC_PATH_PROG(CSC, mono-csc, no)
10 LIB_PREFIX=.so
11 LIB_SUFFIX=
12 fi
13
14=== modified file 'debian/control'
15--- debian/control 2013-12-19 14:37:54 +0000
16+++ debian/control 2016-11-29 17:27:34 +0000
17@@ -8,6 +8,7 @@
18 python-all-dev,
19 at-spi2-core,
20 cli-common-dev (>= 0.5.7) [!arm64 !ppc64el],
21+ gnome-common,
22 gobject-introspection,
23 intltool,
24 gtk-doc-tools,
25
26=== modified file 'debian/rules'
27--- debian/rules 2013-12-19 14:37:54 +0000
28+++ debian/rules 2016-11-29 17:27:34 +0000
29@@ -15,8 +15,6 @@
30 CONFIGURE_FLAGS_gtk2 = --with-gtk=2 --enable-gtk-doc
31 CONFIGURE_FLAGS_gtk3 = --with-gtk=3 --enable-gtk-doc=no
32
33-export CSC=/usr/bin/mono-csc
34-
35 export DPKG_GENSYMBOLS_CHECK_LEVEL = 4
36
37 CFLAGS += -fPIC
38
39=== modified file 'example/simple-client-vala.vala'
40--- example/simple-client-vala.vala 2012-03-21 18:02:41 +0000
41+++ example/simple-client-vala.vala 2016-11-29 17:27:34 +0000
42@@ -104,7 +104,7 @@
43 print(@"Got scroll event! delta: $delta, direction: $direction\n");
44 });
45
46- Timeout.add_seconds(1, () => {
47+ GLib.Timeout.add_seconds(1, () => {
48 percentage = (percentage + 1) % 100;
49 if (can_haz_label) {
50 ci.set_label(@"$(percentage+1)%", "");
51
52=== modified file 'src/app-indicator.c'
53--- src/app-indicator.c 2015-07-02 17:03:37 +0000
54+++ src/app-indicator.c 2016-11-29 17:27:34 +0000
55@@ -38,6 +38,8 @@
56
57 #include <libindicator/indicator-desktop-shortcuts.h>
58
59+#include <stdlib.h>
60+
61 #include "app-indicator.h"
62 #include "app-indicator-enum-types.h"
63 #include "application-service-marshal.h"
64@@ -71,8 +73,11 @@
65 AppIndicatorCategory category;
66 AppIndicatorStatus status;
67 gchar *icon_name;
68+ gchar *absolute_icon_name;
69 gchar *attention_icon_name;
70+ gchar *absolute_attention_icon_name;
71 gchar *icon_theme_path;
72+ gchar *absolute_icon_theme_path;
73 DbusmenuServer *menuservice;
74 GtkWidget *menu;
75 GtkWidget *sec_activate_target;
76@@ -190,6 +195,8 @@
77 static void status_icon_menu_activate (GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data);
78 static void unfallback (AppIndicator * self, GtkStatusIcon * status_icon);
79 static gchar * append_panel_icon_suffix (const gchar * icon_name);
80+static gchar * get_real_theme_path (AppIndicator * self);
81+static gchar * append_snap_prefix (const gchar * path);
82 static void theme_changed_cb (GtkIconTheme * theme, gpointer user_data);
83 static void sec_activate_target_parent_changed(GtkWidget *menuitem, GtkWidget *old_parent, gpointer user_data);
84 static GVariant * bus_get_prop (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * property, GError ** error, gpointer user_data);
85@@ -389,7 +396,7 @@
86 "An additional place to look for icon names that may be installed by the application.",
87 NULL,
88 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT));
89-
90+
91 /**
92 * AppIndicator:connected:
93 *
94@@ -640,6 +647,7 @@
95 app_indicator_init (AppIndicator *self)
96 {
97 AppIndicatorPrivate * priv = APP_INDICATOR_GET_PRIVATE(self);
98+ self->priv = priv;
99
100 priv->id = NULL;
101 priv->clean_id = NULL;
102@@ -648,6 +656,7 @@
103 priv->icon_name = NULL;
104 priv->attention_icon_name = NULL;
105 priv->icon_theme_path = NULL;
106+ priv->absolute_icon_theme_path = get_real_theme_path (self);
107 priv->menu = NULL;
108 priv->menuservice = NULL;
109 priv->ordering_index = 0;
110@@ -676,8 +685,6 @@
111 (GBusNameVanishedCallback) name_vanished_handler,
112 self, NULL);
113
114- self->priv = priv;
115-
116 /* Start getting the session bus */
117 g_object_ref(self); /* ref for the bus creation callback */
118 g_bus_get(G_BUS_TYPE_SESSION, NULL, bus_creation, self);
119@@ -794,16 +801,31 @@
120 priv->icon_name = NULL;
121 }
122
123+ if (priv->absolute_icon_name != NULL) {
124+ g_free(priv->absolute_icon_name);
125+ priv->absolute_icon_name = NULL;
126+ }
127+
128 if (priv->attention_icon_name != NULL) {
129 g_free(priv->attention_icon_name);
130 priv->attention_icon_name = NULL;
131 }
132
133+ if (priv->absolute_attention_icon_name != NULL) {
134+ g_free(priv->absolute_attention_icon_name);
135+ priv->absolute_attention_icon_name = NULL;
136+ }
137+
138 if (priv->icon_theme_path != NULL) {
139 g_free(priv->icon_theme_path);
140 priv->icon_theme_path = NULL;
141 }
142-
143+
144+ if (priv->absolute_icon_theme_path != NULL) {
145+ g_free(priv->absolute_icon_theme_path);
146+ priv->absolute_icon_theme_path = NULL;
147+ }
148+
149 if (priv->title != NULL) {
150 g_free(priv->title);
151 priv->title = NULL;
152@@ -1188,8 +1210,14 @@
153 enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_STATUS), priv->status);
154 return g_variant_new_string(enum_value->value_nick ? enum_value->value_nick : "");
155 } else if (g_strcmp0(property, "IconName") == 0) {
156+ if (priv->absolute_icon_name) {
157+ return g_variant_new_string(priv->absolute_icon_name);
158+ }
159 return g_variant_new_string(priv->icon_name ? priv->icon_name : "");
160 } else if (g_strcmp0(property, "AttentionIconName") == 0) {
161+ if (priv->absolute_attention_icon_name) {
162+ return g_variant_new_string(priv->absolute_attention_icon_name);
163+ }
164 return g_variant_new_string(priv->attention_icon_name ? priv->attention_icon_name : "");
165 } else if (g_strcmp0(property, "Title") == 0) {
166 const gchar * output = NULL;
167@@ -1205,6 +1233,9 @@
168 }
169 return g_variant_new_string(output);
170 } else if (g_strcmp0(property, "IconThemePath") == 0) {
171+ if (priv->absolute_icon_theme_path) {
172+ return g_variant_new_string(priv->absolute_icon_theme_path);
173+ }
174 return g_variant_new_string(priv->icon_theme_path ? priv->icon_theme_path : "");
175 } else if (g_strcmp0(property, "Menu") == 0) {
176 if (priv->menuservice != NULL) {
177@@ -1571,19 +1602,23 @@
178
179 /* add the icon_theme_path once if needed */
180 GtkIconTheme *icon_theme = gtk_icon_theme_get_default();
181- if (self->priv->icon_theme_path != NULL) {
182+ const gchar *theme_path = self->priv->absolute_icon_theme_path ?
183+ self->priv->absolute_icon_theme_path :
184+ self->priv->icon_theme_path;
185+
186+ if (theme_path != NULL) {
187 gchar **path;
188 gint n_elements, i;
189 gboolean found=FALSE;
190 gtk_icon_theme_get_search_path(icon_theme, &path, &n_elements);
191 for (i=0; i< n_elements || path[i] == NULL; i++) {
192- if(g_strcmp0(path[i], self->priv->icon_theme_path) == 0) {
193+ if(g_strcmp0(path[i], theme_path) == 0) {
194 found=TRUE;
195 break;
196 }
197 }
198 if(!found) {
199- gtk_icon_theme_append_search_path(icon_theme, self->priv->icon_theme_path);
200+ gtk_icon_theme_append_search_path(icon_theme, theme_path);
201 }
202 g_strfreev (path);
203 }
204@@ -1607,8 +1642,12 @@
205 };
206
207 if (icon_name != NULL) {
208+ gchar *snapped_icon = append_snap_prefix(icon_name);
209+
210 if (g_file_test(icon_name, G_FILE_TEST_EXISTS)) {
211 gtk_status_icon_set_from_file(icon, icon_name);
212+ } else if (snapped_icon && g_file_test(snapped_icon, G_FILE_TEST_EXISTS)) {
213+ gtk_status_icon_set_from_file(icon, snapped_icon);
214 } else {
215 gchar *longname = append_panel_icon_suffix(icon_name);
216
217@@ -1620,6 +1659,8 @@
218
219 g_free(longname);
220 }
221+
222+ g_free(snapped_icon);
223 }
224
225 return;
226@@ -1633,7 +1674,7 @@
227 GtkMenu * menu = app_indicator_get_menu(APP_INDICATOR(data));
228 if (menu == NULL)
229 return;
230-
231+
232 gtk_menu_popup(menu,
233 NULL, /* Parent Menu */
234 NULL, /* Parent item */
235@@ -1681,7 +1722,7 @@
236 long_name = g_strdup (icon_name);
237 }
238
239- return long_name;
240+ return long_name;
241 }
242
243 static gboolean
244@@ -1858,6 +1899,14 @@
245 if (g_strcmp0 (self->priv->attention_icon_name, icon_name) != 0) {
246 g_free (self->priv->attention_icon_name);
247 self->priv->attention_icon_name = g_strdup (icon_name);
248+
249+ g_free(self->priv->absolute_attention_icon_name);
250+ self->priv->absolute_attention_icon_name = NULL;
251+
252+ if (icon_name && icon_name[0] == '/') {
253+ self->priv->absolute_attention_icon_name = append_snap_prefix (icon_name);
254+ }
255+
256 changed = TRUE;
257 }
258
259@@ -1933,6 +1982,14 @@
260 }
261
262 self->priv->icon_name = g_strdup(icon_name);
263+
264+ g_free(self->priv->absolute_icon_name);
265+ self->priv->absolute_icon_name = NULL;
266+
267+ if (icon_name && icon_name[0] == '/') {
268+ self->priv->absolute_icon_name = append_snap_prefix (icon_name);
269+ }
270+
271 changed = TRUE;
272 }
273
274@@ -1994,6 +2051,54 @@
275 return;
276 }
277
278+static const gchar *
279+get_snap_prefix ()
280+{
281+ const gchar *snap = g_getenv ("SNAP");
282+ return (snap && *snap != '\0') ? snap : NULL;
283+}
284+
285+static gchar *
286+append_snap_prefix (const gchar *path)
287+{
288+ gchar real_path[PATH_MAX];
289+ const gchar *snap = get_snap_prefix ();
290+
291+ if (snap != NULL && path != NULL) {
292+ if (realpath (path, real_path) != NULL) {
293+ path = real_path;
294+ }
295+
296+ if (g_str_has_prefix (path, "/tmp/")) {
297+ g_warning ("Using '/tmp' paths in SNAP environment will lead to unreadable resources");
298+ return NULL;
299+ }
300+
301+ if (g_str_has_prefix (path, snap)) {
302+ return g_strdup (path);
303+ }
304+
305+ return g_build_path (G_DIR_SEPARATOR_S, snap, path, NULL);
306+ }
307+
308+ return NULL;
309+}
310+
311+static gchar *
312+get_real_theme_path (AppIndicator * self)
313+{
314+ const gchar *theme_path = self->priv->icon_theme_path;
315+ gchar *snapped_path = append_snap_prefix (theme_path);
316+
317+ if (snapped_path != NULL) {
318+ return snapped_path;
319+ } else if (get_snap_prefix ()) {
320+ return g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), "icons", NULL);
321+ }
322+
323+ return NULL;
324+}
325+
326 /**
327 * app_indicator_set_icon_theme_path:
328 * @self: The #AppIndicator object to use
329@@ -2012,9 +2117,15 @@
330
331 self->priv->icon_theme_path = g_strdup(icon_theme_path);
332
333+ g_free (self->priv->absolute_icon_theme_path);
334+ self->priv->absolute_icon_theme_path = get_real_theme_path (self);
335+
336 g_signal_emit (self, signals[NEW_ICON_THEME_PATH], 0, self->priv->icon_theme_path, TRUE);
337
338 if (self->priv->dbus_registration != 0 && self->priv->connection != NULL) {
339+ const gchar *theme_path = self->priv->absolute_icon_theme_path ?
340+ self->priv->absolute_icon_theme_path :
341+ self->priv->icon_theme_path;
342 GError * error = NULL;
343
344 g_dbus_connection_emit_signal(self->priv->connection,
345@@ -2022,7 +2133,7 @@
346 self->priv->path,
347 NOTIFICATION_ITEM_DBUS_IFACE,
348 "NewIconThemePath",
349- g_variant_new("(s)", self->priv->icon_theme_path),
350+ g_variant_new("(s)", theme_path ? theme_path : ""),
351 &error);
352
353 if (error != NULL) {

Subscribers

People subscribed via source and target branches