Rework dbus naming conventions to be more friendly with sandboxed
environments.
- XAppStatusIcon users will own the name 'org.x.StatusIcon.progname".
This can also be specified using xapp_status_icon_set_name(), to
assign a particular name, as long as there are 4 parts to the name
in total.
- Each app process will have a GDBusObjectManagerServer singleton
to expose individual icon objects (this keeps the ability to have
multiple status icons from a single process, something xapp-sn-
watcher must have). The server is created when the first icon is
added, and destroyed when the last is removed.
- XAppStatusIconMonitors will host a matching object manager client
for each status icon process it connects with.
This simplifies accounting of icons, as the managers take over
add/remove notifications and proxy creation - we really only need
to keep track of the managers themselves and react to them.
Minor changes to status applets are required to ensure the visual
representations are tracked correctly. Previously, each icon had
a matching unique name on the bus. This name was used as the
identifier to keep track of proxies. Now, there is one name per
process, so the object path will be appended also, to insure
uniqueness.
Michael Webster
3 years ago
0 | #!/usr/bin/env python3 | |
1 | ||
2 | ''' | |
3 | FIXME | |
4 | ||
5 | This script is used only to call gdbus-codegen and simulate the | |
6 | generation of the source code and header as different targets. | |
7 | ||
8 | Both are generated implicitly, so meson is not able to know how | |
9 | many files are generated, so it does generate only one opaque | |
10 | target that represents the two files. | |
11 | ||
12 | originally from: | |
13 | https://gitlab.gnome.org/GNOME/gnome-settings-daemon/commit/5924d72931a030b24554116a48140a661a99652b | |
14 | ||
15 | Please see: | |
16 | https://bugzilla.gnome.org/show_bug.cgi?id=791015 | |
17 | https://github.com/mesonbuild/meson/pull/2930 | |
18 | ''' | |
19 | ||
20 | import subprocess | |
21 | import sys | |
22 | import os | |
23 | ||
24 | subprocess.call([ | |
25 | 'gdbus-codegen', | |
26 | '--interface-prefix=' + sys.argv[1], | |
27 | '--generate-c-code=' + os.path.join(sys.argv[4], sys.argv[2]), | |
28 | '--c-namespace=XApp', | |
29 | '--annotate', sys.argv[1], 'org.gtk.GDBus.C.Name', sys.argv[3], | |
30 | sys.argv[5] | |
31 | ]) |
20 | 20 | #define MONITOR_NAME "org.x.StatusIconMonitor" |
21 | 21 | |
22 | 22 | #define STATUS_ICON_MATCH "org.x.StatusIcon." |
23 | ||
24 | #define STATUS_ICON_ID_FORMAT "org.x.StatusIcon.PID-%d-%d" | |
25 | #define STATUS_ICON_PATH_PREFIX "/org/x/StatusIcon/" | |
23 | #define STATUS_ICON_INTERFACE "org.x.StatusIcon" | |
24 | ||
25 | #define STATUS_ICON_PATH "/org/x/StatusIcon" | |
26 | #define STATUS_ICON_PATH_PREFIX STATUS_ICON_PATH "/" | |
26 | 27 | |
27 | 28 | #define STATUS_NOTIFIER_WATCHER_NAME "org.x.StatusNotifierWatcher" |
28 | 29 | #define WATCHER_MAX_RESTARTS 2 |
58 | 59 | { |
59 | 60 | GDBusConnection *connection; |
60 | 61 | |
61 | GHashTable *icons; | |
62 | gchar *name; | |
62 | GHashTable *object_managers; | |
63 | 63 | |
64 | 64 | guint owner_id; |
65 | 65 | guint listener_id; |
66 | guint sn_watcher_id; | |
67 | ||
68 | guint sn_watcher_retry_count; | |
69 | ||
70 | 66 | } XAppStatusIconMonitorPrivate; |
71 | 67 | |
72 | 68 | struct _XAppStatusIconMonitor |
76 | 72 | |
77 | 73 | G_DEFINE_TYPE_WITH_PRIVATE (XAppStatusIconMonitor, xapp_status_icon_monitor, G_TYPE_OBJECT) |
78 | 74 | |
79 | static void remove_icon (XAppStatusIconMonitor *self, const gchar *name); | |
80 | ||
81 | static void | |
82 | on_proxy_name_owner_changed (GObject *object, | |
83 | GParamSpec *pspec, | |
84 | gpointer user_data) | |
85 | { | |
86 | XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data); | |
87 | ||
88 | gchar *name_owner = NULL; | |
89 | gchar *proxy_name = NULL; | |
75 | static void | |
76 | on_object_manager_name_owner_changed (GObject *object, | |
77 | GParamSpec *pspec, | |
78 | gpointer user_data) | |
79 | { | |
80 | XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data); | |
81 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); | |
82 | gchar *name, *owner; | |
90 | 83 | |
91 | 84 | g_object_get (object, |
92 | "g-name-owner", &name_owner, | |
93 | "g-name", &proxy_name, | |
85 | "name-owner", &owner, | |
86 | "name", &name, | |
94 | 87 | NULL); |
95 | 88 | |
96 | g_debug("XAppStatusIconMonitor: proxy name owner changed - name owner '%s' is now '%s')", proxy_name, name_owner); | |
97 | ||
98 | if (name_owner == NULL) | |
99 | { | |
100 | remove_icon (self, proxy_name); | |
101 | } | |
102 | ||
103 | g_free (name_owner); | |
104 | g_free (proxy_name); | |
105 | } | |
106 | ||
107 | static void | |
108 | remove_icon (XAppStatusIconMonitor *self, | |
109 | const gchar *name) | |
110 | { | |
111 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); | |
112 | XAppStatusIconInterface *proxy; | |
113 | ||
114 | proxy = g_hash_table_lookup (priv->icons, name); | |
115 | ||
116 | if (proxy) | |
117 | { | |
118 | g_object_ref (proxy); | |
119 | ||
120 | g_signal_handlers_disconnect_by_func (proxy, | |
121 | on_proxy_name_owner_changed, | |
122 | self); | |
123 | ||
124 | if (g_hash_table_remove (priv->icons, name)) | |
125 | { | |
126 | g_debug("XAppStatusIconMonitor: removing icon: '%s'", name); | |
127 | ||
128 | g_signal_emit (self, signals[ICON_REMOVED], 0, proxy); | |
129 | } | |
130 | else | |
131 | { | |
132 | g_assert_not_reached (); | |
133 | } | |
134 | ||
135 | g_object_unref (proxy); | |
136 | } | |
137 | } | |
138 | ||
139 | static void | |
140 | new_status_icon_proxy_complete (GObject *object, | |
141 | GAsyncResult *res, | |
142 | gpointer user_data) | |
143 | { | |
144 | XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data); | |
145 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); | |
146 | XAppStatusIconInterface *proxy; | |
89 | g_debug("XAppStatusIconMonitor: app name owner changed - name '%s' is now %s)", | |
90 | name, owner != NULL ? "owned" : "unowned"); | |
91 | ||
92 | if (owner == NULL) | |
93 | { | |
94 | g_hash_table_remove (priv->object_managers, name); | |
95 | } | |
96 | ||
97 | g_free (owner); | |
98 | g_free (name); | |
99 | } | |
100 | ||
101 | static void | |
102 | object_manager_object_added (XAppObjectManagerClient *manager, | |
103 | GDBusObject *object, | |
104 | gpointer user_data) | |
105 | { | |
106 | XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data); | |
107 | GDBusInterface *proxy; | |
108 | ||
109 | proxy = g_dbus_object_get_interface (object, STATUS_ICON_INTERFACE); | |
110 | ||
111 | g_signal_emit (self, signals[ICON_ADDED], 0, XAPP_STATUS_ICON_INTERFACE_PROXY (proxy)); | |
112 | ||
113 | g_object_unref (proxy); | |
114 | } | |
115 | ||
116 | static void | |
117 | object_manager_object_removed (XAppObjectManagerClient *manager, | |
118 | GDBusObject *object, | |
119 | gpointer user_data) | |
120 | { | |
121 | XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data); | |
122 | GDBusInterface *proxy; | |
123 | ||
124 | proxy = g_dbus_object_get_interface (object, STATUS_ICON_INTERFACE); | |
125 | ||
126 | g_signal_emit (self, signals[ICON_REMOVED], 0, XAPP_STATUS_ICON_INTERFACE_PROXY (proxy)); | |
127 | ||
128 | g_object_unref (proxy); | |
129 | } | |
130 | ||
131 | static void | |
132 | new_object_manager_created (GObject *object, | |
133 | GAsyncResult *res, | |
134 | gpointer user_data) | |
135 | { | |
136 | XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data); | |
137 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); | |
138 | GDBusObjectManager *obj_mgr; | |
139 | GList *objects = NULL, *iter; | |
140 | ||
147 | 141 | GError *error; |
148 | gchar *g_name; | |
142 | gchar *name; | |
149 | 143 | |
150 | 144 | error = NULL; |
151 | 145 | |
152 | proxy = xapp_status_icon_interface_proxy_new_finish (res, | |
153 | &error); | |
146 | obj_mgr = xapp_object_manager_client_new_finish (res, | |
147 | &error); | |
154 | 148 | |
155 | 149 | if (error) |
156 | 150 | { |
157 | g_warning ("Couldn't add status icon: %s", error->message); | |
151 | g_warning ("Couldn't create object manager for bus name: %s", error->message); | |
158 | 152 | g_error_free (error); |
159 | 153 | return; |
160 | 154 | } |
161 | 155 | |
162 | g_signal_connect_object (proxy, | |
163 | "notify::g-name-owner", | |
164 | G_CALLBACK (on_proxy_name_owner_changed), | |
165 | self, | |
166 | 0); | |
167 | ||
168 | g_object_get (proxy, "g-name", &g_name, NULL); | |
169 | ||
170 | g_hash_table_insert (priv->icons, | |
171 | g_name, | |
172 | proxy); | |
173 | ||
174 | g_signal_emit (self, signals[ICON_ADDED], 0, proxy); | |
175 | } | |
176 | ||
177 | static void | |
178 | add_icon (XAppStatusIconMonitor *self, | |
179 | const gchar *name) | |
180 | { | |
181 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); | |
182 | gchar *unique_path; | |
183 | gint pid, id; | |
184 | ||
185 | if (sscanf (name, STATUS_ICON_ID_FORMAT, &pid, &id) == 2) | |
186 | { | |
187 | unique_path = g_strdup_printf (STATUS_ICON_PATH_PREFIX "%d", id); | |
188 | ||
189 | g_debug("XAppStatusIconMonitor: adding icon: '%s' with path '%s'", name, unique_path); | |
190 | ||
191 | xapp_status_icon_interface_proxy_new (priv->connection, | |
192 | G_DBUS_PROXY_FLAGS_NONE, | |
193 | name, | |
194 | unique_path, | |
195 | NULL, | |
196 | new_status_icon_proxy_complete, | |
197 | self); | |
198 | ||
199 | g_free (unique_path); | |
156 | g_object_get (obj_mgr, "name", &name, NULL); | |
157 | ||
158 | g_debug("XAppStatusIconMonitor: Object manager added for new bus name: '%s'", name); | |
159 | ||
160 | g_signal_connect (obj_mgr, | |
161 | "notify::name-owner", | |
162 | G_CALLBACK (on_object_manager_name_owner_changed), | |
163 | self); | |
164 | ||
165 | g_signal_connect (obj_mgr, | |
166 | "object-added", | |
167 | G_CALLBACK (object_manager_object_added), | |
168 | self); | |
169 | ||
170 | g_signal_connect (obj_mgr, | |
171 | "object-removed", | |
172 | G_CALLBACK (object_manager_object_removed), | |
173 | self); | |
174 | ||
175 | g_hash_table_insert (priv->object_managers, | |
176 | name, | |
177 | obj_mgr); | |
178 | ||
179 | objects = g_dbus_object_manager_get_objects (obj_mgr); | |
180 | ||
181 | for (iter = objects; iter != NULL; iter = iter->next) | |
182 | { | |
183 | GDBusObject *object = G_DBUS_OBJECT (iter->data); | |
184 | GDBusInterface *proxy = g_dbus_object_get_interface (object, STATUS_ICON_INTERFACE); | |
185 | ||
186 | g_signal_emit (self, signals[ICON_ADDED], 0, proxy); | |
187 | ||
188 | g_object_unref (proxy); | |
189 | } | |
190 | ||
191 | g_list_free_full (objects, g_object_unref); | |
192 | } | |
193 | ||
194 | static void | |
195 | add_object_manager_for_name (XAppStatusIconMonitor *self, | |
196 | const gchar *name) | |
197 | { | |
198 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); | |
199 | gchar **name_parts = NULL; | |
200 | ||
201 | name_parts = g_strsplit (name, ".", -1); | |
202 | ||
203 | if (g_strv_length (name_parts) == 4) | |
204 | { | |
205 | xapp_object_manager_client_new (priv->connection, | |
206 | G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, | |
207 | name, | |
208 | STATUS_ICON_PATH, | |
209 | NULL, | |
210 | new_object_manager_created, | |
211 | self); | |
200 | 212 | } |
201 | 213 | else |
202 | 214 | { |
203 | g_debug ("XAppStatusIconMonitor: adding icon failed, name '%s' is invalid", name); | |
204 | } | |
215 | g_debug ("XAppStatusIconMonitor: adding object manager failed, bus name '%s' is invalid", name); | |
216 | } | |
217 | ||
218 | g_strfreev (name_parts); | |
205 | 219 | } |
206 | 220 | |
207 | 221 | static void |
235 | 249 | /* the '.' at the end so we don't catch ourselves in this */ |
236 | 250 | if (g_str_has_prefix (str, STATUS_ICON_MATCH)) |
237 | 251 | { |
238 | g_debug ("XAppStatusIconMonitor: found icon: %s", str); | |
239 | add_icon (self, str); | |
252 | g_debug ("XAppStatusIconMonitor: found new status icon app: %s", str); | |
253 | add_object_manager_for_name (self, str); | |
240 | 254 | } |
241 | 255 | } |
242 | 256 | |
249 | 263 | { |
250 | 264 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); |
251 | 265 | |
252 | ||
253 | g_debug("XAppStatusIconMonitor: looking for status icons on the bus"); | |
266 | g_debug("XAppStatusIconMonitor: looking for status icon apps on the bus"); | |
254 | 267 | |
255 | 268 | /* If there are no monitors (applets) already running when this is set up, |
256 | 269 | * this won't find anything. The XAppStatusIcons will be in fallback mode, |
289 | 302 | } |
290 | 303 | |
291 | 304 | static void |
292 | status_icon_name_appeared (XAppStatusIconMonitor *self, | |
293 | const gchar *name, | |
294 | const gchar *owner) | |
295 | { | |
296 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); | |
297 | ||
298 | if (!g_str_has_prefix (name, STATUS_ICON_MATCH)) | |
299 | { | |
300 | return; | |
301 | } | |
302 | ||
303 | if (g_hash_table_contains (priv->icons, name)) | |
304 | { | |
305 | return; | |
306 | } | |
307 | ||
308 | g_debug ("XAppStatusIconMonitor: new icon appeared: %s", name); | |
309 | ||
310 | add_icon (self, name); | |
311 | } | |
312 | ||
313 | static void | |
314 | status_icon_name_vanished (XAppStatusIconMonitor *self, | |
315 | const gchar *name) | |
316 | { | |
317 | if (!g_str_has_prefix (name, STATUS_ICON_MATCH)) | |
318 | { | |
319 | return; | |
320 | } | |
321 | ||
322 | g_debug ("XAppStatusIconMonitor: icon presence vanished: %s", name); | |
323 | ||
324 | remove_icon (self, name); | |
325 | } | |
326 | ||
327 | static void | |
328 | 305 | name_owner_changed (GDBusConnection *connection, |
329 | 306 | const gchar *sender_name, |
330 | 307 | const gchar *object_path, |
343 | 320 | |
344 | 321 | g_variant_get (parameters, "(&s&s&s)", &name, &old_owner, &new_owner); |
345 | 322 | |
346 | if (old_owner[0] != '\0') | |
347 | { | |
348 | status_icon_name_vanished (self, name); | |
349 | } | |
350 | ||
351 | 323 | if (new_owner[0] != '\0') |
352 | 324 | { |
353 | status_icon_name_appeared (self, name, new_owner); | |
354 | } | |
355 | } | |
356 | ||
325 | add_object_manager_for_name (self, name); | |
326 | } | |
327 | } | |
357 | 328 | |
358 | 329 | static void |
359 | 330 | add_name_listener (XAppStatusIconMonitor *self) |
360 | 331 | { |
361 | 332 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); |
362 | 333 | |
363 | g_debug ("XAppStatusIconMonitor: Adding NameOwnerChanged listener for status icons"); | |
334 | g_debug ("XAppStatusIconMonitor: Adding NameOwnerChanged listener for status icon apps"); | |
364 | 335 | |
365 | 336 | priv->listener_id = g_dbus_connection_signal_subscribe (priv->connection, |
366 | 337 | "org.freedesktop.DBus", |
392 | 363 | { |
393 | 364 | XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data); |
394 | 365 | |
395 | g_debug ("XAppStatusIconMonitor: name acquired on dbus"); | |
366 | g_debug ("XAppStatusIconMonitor: Name owned on bus: %s", name); | |
396 | 367 | |
397 | 368 | add_name_listener (self); |
398 | 369 | find_and_add_icons (self); |
407 | 378 | XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data); |
408 | 379 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); |
409 | 380 | |
410 | g_debug ("XAppStatusIconMonitor: session bus connection acquired"); | |
381 | g_debug ("XAppStatusIconMonitor: Connected to bus: %s", name); | |
411 | 382 | |
412 | 383 | priv->connection = connection; |
413 | 384 | } |
416 | 387 | connect_to_bus (XAppStatusIconMonitor *self) |
417 | 388 | { |
418 | 389 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); |
419 | ||
390 | gchar *valid_app_name, *owned_name; | |
420 | 391 | static gint unique_id = 0; |
421 | 392 | |
422 | char *owner_name = g_strdup_printf("%s.PID-%d-%d", MONITOR_NAME, getpid (), unique_id); | |
423 | ||
424 | unique_id++; | |
425 | ||
426 | g_debug ("XAppStatusIconMonitor: Attempting to acquire presence on dbus as %s", owner_name); | |
393 | valid_app_name = g_strdelimit (g_strdup (g_get_application_name ()), ".-,=+~`/", '_'); | |
394 | owned_name = g_strdup_printf ("%s.%s_%d", MONITOR_NAME, valid_app_name, unique_id++); | |
395 | g_free (valid_app_name); | |
396 | ||
397 | g_debug ("XAppStatusIconMonitor: Attempting to own name on bus: %s", owned_name); | |
427 | 398 | |
428 | 399 | priv->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, |
429 | owner_name, | |
400 | owned_name, | |
430 | 401 | G_DBUS_CONNECTION_FLAGS_NONE, |
431 | 402 | on_bus_acquired, |
432 | 403 | on_name_acquired, |
434 | 405 | self, |
435 | 406 | NULL); |
436 | 407 | |
437 | g_free(owner_name); | |
408 | g_free(owned_name); | |
438 | 409 | } |
439 | 410 | |
440 | 411 | static void |
442 | 413 | { |
443 | 414 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self); |
444 | 415 | |
445 | priv->name = g_strdup_printf("%s", g_get_application_name()); | |
446 | ||
447 | priv->icons = g_hash_table_new_full (g_str_hash, g_str_equal, | |
448 | g_free, g_object_unref); | |
449 | ||
450 | priv->sn_watcher_retry_count = 0; | |
416 | priv->object_managers = g_hash_table_new_full (g_str_hash, g_str_equal, | |
417 | g_free, g_object_unref); | |
451 | 418 | |
452 | 419 | connect_to_bus (self); |
453 | 420 | } |
468 | 435 | priv->listener_id = 0; |
469 | 436 | } |
470 | 437 | |
438 | if (priv->object_managers != NULL) | |
439 | { | |
440 | g_hash_table_unref (priv->object_managers); | |
441 | priv->object_managers = NULL; | |
442 | } | |
443 | ||
471 | 444 | if (priv->owner_id > 0) |
472 | 445 | { |
473 | 446 | g_bus_unown_name(priv->owner_id); |
474 | 447 | priv->owner_id = 0; |
475 | 448 | } |
476 | 449 | |
477 | if (priv->sn_watcher_id > 0) | |
478 | { | |
479 | g_bus_unwatch_name (priv->sn_watcher_id); | |
480 | priv->sn_watcher_id = 0; | |
481 | } | |
482 | ||
483 | 450 | g_clear_object (&priv->connection); |
484 | 451 | } |
485 | ||
486 | g_free (priv->name); | |
487 | g_clear_pointer (&priv->icons, g_hash_table_unref); | |
488 | 452 | |
489 | 453 | G_OBJECT_CLASS (xapp_status_icon_monitor_parent_class)->dispose (object); |
490 | 454 | } |
538 | 502 | G_TYPE_NONE, 1, XAPP_TYPE_STATUS_ICON_INTERFACE_PROXY); |
539 | 503 | } |
540 | 504 | |
505 | static void | |
506 | gather_objects_foreach_func (gpointer key, | |
507 | gpointer value, | |
508 | gpointer user_data) | |
509 | { | |
510 | GDBusObjectManager *obj_mgr = G_DBUS_OBJECT_MANAGER (value); | |
511 | GList **ret = (GList **) user_data; | |
512 | ||
513 | GList *objects = NULL, *iter; | |
514 | ||
515 | objects = g_dbus_object_manager_get_objects (obj_mgr); | |
516 | ||
517 | for (iter = objects; iter != NULL; iter = iter->next) | |
518 | { | |
519 | GDBusObject *object = G_DBUS_OBJECT (iter->data); | |
520 | GDBusInterface *proxy = g_dbus_object_get_interface (object, STATUS_ICON_INTERFACE); | |
521 | ||
522 | *ret = g_list_prepend (*ret, proxy); | |
523 | ||
524 | g_object_unref (proxy); | |
525 | } | |
526 | ||
527 | g_list_free_full (objects, g_object_unref); | |
528 | } | |
529 | ||
541 | 530 | /** |
542 | 531 | * xapp_status_icon_monitor_list_icons: |
543 | 532 | * @monitor: a #XAppStatusIconMonitor |
552 | 541 | xapp_status_icon_monitor_list_icons (XAppStatusIconMonitor *monitor) |
553 | 542 | { |
554 | 543 | g_return_val_if_fail (XAPP_IS_STATUS_ICON_MONITOR (monitor), NULL); |
544 | GList *ret = NULL; | |
555 | 545 | |
556 | 546 | XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (monitor); |
557 | 547 | |
558 | return g_hash_table_get_values (priv->icons); | |
548 | g_hash_table_foreach (priv->object_managers, | |
549 | (GHFunc) gather_objects_foreach_func, | |
550 | &ret); | |
551 | ||
552 | return ret; | |
559 | 553 | } |
560 | 554 | |
561 | 555 | /** |
19 | 19 | #define FDO_DBUS_NAME "org.freedesktop.DBus" |
20 | 20 | #define FDO_DBUS_PATH "/org/freedesktop/DBus" |
21 | 21 | |
22 | #define ICON_PATH "/org/x/StatusIcon" | |
22 | #define ICON_BASE_PATH "/org/x/StatusIcon" | |
23 | #define ICON_SUB_PATH (ICON_BASE_PATH "/Icon") | |
23 | 24 | #define ICON_NAME "org.x.StatusIcon" |
24 | 25 | |
25 | 26 | #define STATUS_ICON_MONITOR_MATCH "org.x.StatusIconMonitor" |
29 | 30 | #define MAX_SANE_ICON_SIZE 96 |
30 | 31 | #define FALLBACK_ICON_SIZE 24 |
31 | 32 | |
32 | static gint unique_id = 0; | |
33 | // This gets reffed and unreffed according to individual icon presence. | |
34 | // For the first icon, it gets created when exporting the icon's inteface. | |
35 | // For each additional icon, it gets reffed again. On destruction, the | |
36 | // opposite occurs - unrefs, and the final unref calls a weak notify | |
37 | // function, which clears this pointer and unown's the process's bus name. | |
38 | static GDBusObjectManagerServer *obj_server = NULL; | |
39 | static guint name_owner_id = 0; | |
33 | 40 | |
34 | 41 | enum |
35 | 42 | { |
49 | 56 | PROP_PRIMARY_MENU, |
50 | 57 | PROP_SECONDARY_MENU, |
51 | 58 | PROP_ICON_SIZE, |
59 | PROP_NAME, | |
52 | 60 | N_PROPERTIES |
53 | 61 | }; |
54 | 62 | |
66 | 74 | */ |
67 | 75 | typedef struct |
68 | 76 | { |
69 | XAppStatusIconInterface *skeleton; | |
70 | 77 | GDBusConnection *connection; |
78 | XAppStatusIconInterface *interface_skeleton; | |
79 | XAppObjectSkeleton *object_skeleton; | |
71 | 80 | |
72 | 81 | GCancellable *cancellable; |
73 | 82 | |
85 | 94 | gint icon_size; |
86 | 95 | gchar *metadata; |
87 | 96 | |
88 | guint owner_id; | |
89 | 97 | guint listener_id; |
90 | 98 | |
91 | 99 | gint fail_counter; |
102 | 110 | |
103 | 111 | static void refresh_icon (XAppStatusIcon *self); |
104 | 112 | static void use_gtk_status_icon (XAppStatusIcon *self); |
105 | static void tear_down_dbus (XAppStatusIcon *self); | |
113 | static void remove_icon_path_from_bus (XAppStatusIcon *self); | |
106 | 114 | |
107 | 115 | static void |
108 | 116 | cancellable_reset (XAppStatusIcon *self) |
265 | 273 | |
266 | 274 | if (icon->priv->state == XAPP_STATUS_ICON_STATE_NATIVE) |
267 | 275 | { |
268 | xapp_status_icon_interface_set_primary_menu_is_open (icon->priv->skeleton, FALSE); | |
276 | xapp_status_icon_interface_set_primary_menu_is_open (icon->priv->interface_skeleton, FALSE); | |
269 | 277 | } |
270 | 278 | |
271 | 279 | g_signal_handlers_disconnect_by_func (widget, primary_menu_unmapped, icon); |
282 | 290 | |
283 | 291 | if (icon->priv->state == XAPP_STATUS_ICON_STATE_NATIVE) |
284 | 292 | { |
285 | xapp_status_icon_interface_set_secondary_menu_is_open (icon->priv->skeleton, FALSE); | |
293 | xapp_status_icon_interface_set_secondary_menu_is_open (icon->priv->interface_skeleton, FALSE); | |
286 | 294 | } |
287 | 295 | |
288 | 296 | g_signal_handlers_disconnect_by_func (widget, secondary_menu_unmapped, icon); |
327 | 335 | { |
328 | 336 | if (self->priv->state == XAPP_STATUS_ICON_STATE_NATIVE) |
329 | 337 | { |
330 | xapp_status_icon_interface_set_primary_menu_is_open (self->priv->skeleton, TRUE); | |
338 | xapp_status_icon_interface_set_primary_menu_is_open (self->priv->interface_skeleton, TRUE); | |
331 | 339 | } |
332 | 340 | |
333 | 341 | g_signal_connect (gtk_widget_get_toplevel (GTK_WIDGET (menu)), |
340 | 348 | { |
341 | 349 | if (self->priv->state == XAPP_STATUS_ICON_STATE_NATIVE) |
342 | 350 | { |
343 | xapp_status_icon_interface_set_secondary_menu_is_open (self->priv->skeleton, TRUE); | |
351 | xapp_status_icon_interface_set_secondary_menu_is_open (self->priv->interface_skeleton, TRUE); | |
344 | 352 | } |
345 | 353 | |
346 | 354 | g_signal_connect (gtk_widget_get_toplevel (GTK_WIDGET (menu)), |
728 | 736 | |
729 | 737 | g_clear_object (&self->priv->gtk_status_icon); |
730 | 738 | |
731 | g_object_set (G_OBJECT (priv->skeleton), | |
739 | g_object_set (G_OBJECT (priv->interface_skeleton), | |
732 | 740 | "name", priv->name, |
733 | 741 | "label", priv->label, |
734 | 742 | "icon-name", priv->icon_name, |
737 | 745 | "metadata", priv->metadata, |
738 | 746 | NULL); |
739 | 747 | |
740 | g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (priv->skeleton)); | |
748 | g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (priv->interface_skeleton)); | |
741 | 749 | } |
742 | 750 | |
743 | 751 | static void |
769 | 777 | { "handle-scroll", handle_scroll_method } |
770 | 778 | }; |
771 | 779 | |
780 | static void | |
781 | obj_server_finalized (gpointer data, | |
782 | GObject *object) | |
783 | { | |
784 | g_debug ("XAppStatusIcon: Final icon removed, clearing object manager (%s)", g_get_application_name ()); | |
785 | ||
786 | if (name_owner_id > 0) | |
787 | { | |
788 | g_bus_unown_name(name_owner_id); | |
789 | name_owner_id = 0; | |
790 | } | |
791 | ||
792 | obj_server = NULL; | |
793 | } | |
794 | ||
795 | static void | |
796 | ensure_object_manager (XAppStatusIcon *self) | |
797 | { | |
798 | if (obj_server == NULL) | |
799 | { | |
800 | g_debug ("XAppStatusIcon: New object manager for (%s)", g_get_application_name ()); | |
801 | ||
802 | obj_server = g_dbus_object_manager_server_new (ICON_BASE_PATH); | |
803 | g_dbus_object_manager_server_set_connection (obj_server, self->priv->connection); | |
804 | g_object_weak_ref (G_OBJECT (obj_server),(GWeakNotify) obj_server_finalized, self); | |
805 | } | |
806 | else | |
807 | { | |
808 | g_object_ref (obj_server); | |
809 | } | |
810 | } | |
811 | ||
772 | 812 | static gboolean |
773 | 813 | export_icon_interface (XAppStatusIcon *self) |
774 | 814 | { |
775 | GError *error = NULL; | |
776 | 815 | gint i; |
777 | gchar *unique_path; | |
778 | ||
779 | if (self->priv->skeleton) { | |
816 | ||
817 | ensure_object_manager (self); | |
818 | ||
819 | if (self->priv->interface_skeleton) | |
820 | { | |
780 | 821 | return TRUE; |
781 | 822 | } |
782 | 823 | |
783 | self->priv->skeleton = xapp_status_icon_interface_skeleton_new (); | |
784 | ||
785 | unique_path = g_strdup_printf (ICON_PATH "/%d", unique_id); | |
786 | ||
787 | g_debug ("XAppStatusIcon: exporting StatusIcon dbus interface to %s", unique_path); | |
788 | ||
789 | g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->priv->skeleton), | |
790 | self->priv->connection, | |
791 | unique_path, | |
792 | &error); | |
793 | ||
794 | g_free (unique_path); | |
795 | ||
796 | if (error != NULL) { | |
797 | g_critical ("XAppStatusIcon: could not export StatusIcon interface: %s", error->message); | |
798 | g_error_free (error); | |
799 | ||
800 | return FALSE; | |
801 | } | |
824 | self->priv->object_skeleton = xapp_object_skeleton_new (ICON_SUB_PATH); | |
825 | self->priv->interface_skeleton = xapp_status_icon_interface_skeleton_new (); | |
826 | ||
827 | xapp_object_skeleton_set_status_icon_interface (self->priv->object_skeleton, | |
828 | self->priv->interface_skeleton); | |
829 | ||
830 | g_dbus_object_manager_server_export_uniquely (obj_server, | |
831 | G_DBUS_OBJECT_SKELETON (self->priv->object_skeleton)); | |
832 | ||
833 | g_object_unref (self->priv->object_skeleton); | |
834 | g_object_unref (self->priv->interface_skeleton); | |
802 | 835 | |
803 | 836 | for (i = 0; i < G_N_ELEMENTS (skeleton_signals); i++) { |
804 | 837 | SkeletonSignal sig = skeleton_signals[i]; |
805 | 838 | |
806 | g_signal_connect (self->priv->skeleton, | |
839 | g_signal_connect (self->priv->interface_skeleton, | |
807 | 840 | sig.signal_name, |
808 | 841 | G_CALLBACK (sig.callback), |
809 | 842 | self); |
815 | 848 | static void |
816 | 849 | connect_with_status_applet (XAppStatusIcon *self) |
817 | 850 | { |
818 | ||
819 | char *owner_name = g_strdup_printf("%s.PID-%d-%d", ICON_NAME, getpid (), unique_id); | |
820 | ||
821 | unique_id++; | |
822 | ||
823 | g_debug ("XAppStatusIcon: Attempting to acquire presence on dbus as %s", owner_name); | |
824 | ||
825 | self->priv->owner_id = g_bus_own_name_on_connection (self->priv->connection, | |
826 | owner_name, | |
827 | G_DBUS_CONNECTION_FLAGS_NONE, | |
828 | on_name_acquired, | |
829 | on_name_lost, | |
830 | self, | |
831 | NULL); | |
851 | gchar **name_parts = NULL; | |
852 | gchar *owner_name; | |
853 | ||
854 | name_parts = g_strsplit (self->priv->name, ".", -1); | |
855 | ||
856 | if (g_dbus_is_name (self->priv->name) && | |
857 | g_str_has_prefix (self->priv->name, ICON_NAME) && | |
858 | g_strv_length (name_parts) == 4) | |
859 | { | |
860 | owner_name = g_strdup (self->priv->name); | |
861 | } | |
862 | else | |
863 | { | |
864 | gchar *valid_app_name = g_strdelimit (g_strdup (g_get_application_name ()), " .-,=+~`/", '_'); | |
865 | ||
866 | owner_name = g_strdup_printf ("%s.%s", | |
867 | ICON_NAME, | |
868 | valid_app_name); | |
869 | g_free (valid_app_name); | |
870 | } | |
871 | ||
872 | g_strfreev (name_parts); | |
873 | ||
874 | if (name_owner_id == 0) | |
875 | { | |
876 | g_debug ("XAppStatusIcon: Attempting to own name on bus '%s'", owner_name); | |
877 | name_owner_id = g_bus_own_name_on_connection (self->priv->connection, | |
878 | owner_name, | |
879 | G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE, | |
880 | on_name_acquired, | |
881 | on_name_lost, | |
882 | self, | |
883 | NULL); | |
884 | } | |
832 | 885 | |
833 | 886 | g_free(owner_name); |
834 | 887 | } |
895 | 948 | |
896 | 949 | g_debug ("XAppStatusIcon: falling back to GtkStatusIcon"); |
897 | 950 | |
898 | tear_down_dbus (self); | |
951 | remove_icon_path_from_bus (self); | |
899 | 952 | |
900 | 953 | // Make sure there wasn't already one |
901 | 954 | g_clear_object (&self->priv->gtk_status_icon); |
970 | 1023 | |
971 | 1024 | if (found && export_icon_interface (self)) |
972 | 1025 | { |
973 | if (self->priv->owner_id > 0) | |
1026 | if (name_owner_id > 0) | |
974 | 1027 | { |
975 | g_debug ("XAppStatusIcon: We already exist on the bus, syncing icon properties"); | |
976 | 1028 | sync_skeleton (self); |
977 | 1029 | } |
978 | 1030 | else |
1064 | 1116 | return; |
1065 | 1117 | } |
1066 | 1118 | |
1067 | if (self->priv->connection) | |
1068 | { | |
1069 | complete_icon_setup (self); | |
1070 | return; | |
1071 | } | |
1072 | ||
1073 | use_gtk_status_icon (self); | |
1119 | complete_icon_setup (self); | |
1074 | 1120 | } |
1075 | 1121 | |
1076 | 1122 | static void |
1077 | 1123 | refresh_icon (XAppStatusIcon *self) |
1078 | 1124 | { |
1079 | if (!self->priv->connection) | |
1080 | { | |
1081 | g_debug ("XAppStatusIcon: Trying to acquire session bus connection"); | |
1125 | if (self->priv->connection == NULL) | |
1126 | { | |
1127 | g_debug ("XAppStatusIcon: Connecting to session bus"); | |
1082 | 1128 | |
1083 | 1129 | cancellable_reset (self); |
1084 | 1130 | |
1110 | 1156 | case PROP_ICON_SIZE: |
1111 | 1157 | XAPP_STATUS_ICON (object)->priv->icon_size = CLAMP (g_value_get_int (value), 0, MAX_SANE_ICON_SIZE); |
1112 | 1158 | break; |
1159 | case PROP_NAME: | |
1160 | xapp_status_icon_set_name (XAPP_STATUS_ICON (object), g_value_get_string (value)); | |
1161 | break; | |
1113 | 1162 | default: |
1114 | 1163 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
1115 | 1164 | break; |
1135 | 1184 | case PROP_ICON_SIZE: |
1136 | 1185 | g_value_set_int (value, icon->priv->icon_size); |
1137 | 1186 | break; |
1187 | case PROP_NAME: | |
1188 | g_value_set_string (value, icon->priv->name); | |
1189 | break; | |
1138 | 1190 | default: |
1139 | 1191 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
1140 | 1192 | break; |
1146 | 1198 | { |
1147 | 1199 | self->priv = xapp_status_icon_get_instance_private (self); |
1148 | 1200 | |
1149 | self->priv->name = g_strdup_printf("%s", g_get_application_name()); | |
1201 | self->priv->name = g_strdup (g_get_application_name()); | |
1202 | ||
1150 | 1203 | self->priv->state = XAPP_STATUS_ICON_STATE_NO_SUPPORT; |
1151 | 1204 | self->priv->icon_size = FALLBACK_ICON_SIZE; |
1152 | 1205 | self->priv->icon_name = g_strdup (" "); |
1160 | 1213 | } |
1161 | 1214 | |
1162 | 1215 | static void |
1163 | tear_down_dbus (XAppStatusIcon *self) | |
1216 | remove_icon_path_from_bus (XAppStatusIcon *self) | |
1164 | 1217 | { |
1165 | 1218 | g_return_if_fail (XAPP_IS_STATUS_ICON (self)); |
1166 | 1219 | |
1167 | if (self->priv->owner_id > 0) | |
1168 | { | |
1169 | g_debug ("XAppStatusIcon: removing dbus presence (%p)", self); | |
1170 | ||
1171 | g_bus_unown_name(self->priv->owner_id); | |
1172 | self->priv->owner_id = 0; | |
1173 | } | |
1174 | ||
1175 | if (self->priv->skeleton) | |
1176 | { | |
1177 | g_debug ("XAppStatusIcon: removing dbus interface (%p)", self); | |
1178 | ||
1179 | g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self->priv->skeleton)); | |
1180 | g_object_unref (self->priv->skeleton); | |
1181 | self->priv->skeleton = NULL; | |
1220 | if (self->priv->object_skeleton) | |
1221 | { | |
1222 | const gchar *path; | |
1223 | path = g_dbus_object_get_object_path (G_DBUS_OBJECT (self->priv->object_skeleton)); | |
1224 | ||
1225 | g_debug ("XAppStatusIcon: removing interface at path '%s'", path); | |
1226 | ||
1227 | g_dbus_object_manager_server_unexport (obj_server, path); | |
1228 | self->priv->interface_skeleton = NULL; | |
1229 | self->priv->object_skeleton = NULL; | |
1230 | ||
1231 | g_object_unref (obj_server); | |
1182 | 1232 | } |
1183 | 1233 | } |
1184 | 1234 | |
1208 | 1258 | self->priv->gtk_status_icon = NULL; |
1209 | 1259 | } |
1210 | 1260 | |
1211 | tear_down_dbus (self); | |
1261 | remove_icon_path_from_bus (self); | |
1212 | 1262 | |
1213 | 1263 | if (self->priv->listener_id > 0) |
1214 | 1264 | { |
1215 | 1265 | g_dbus_connection_signal_unsubscribe (self->priv->connection, self->priv->listener_id); |
1266 | self->priv->listener_id = 0; | |
1216 | 1267 | } |
1217 | 1268 | |
1218 | 1269 | g_clear_object (&self->priv->connection); |
1317 | 1368 | G_PARAM_READWRITE)); |
1318 | 1369 | |
1319 | 1370 | /** |
1371 | * XAppStatusIcon:name: | |
1372 | * | |
1373 | * The name of the icon for sorting purposes. If this is in the form of 'org.x.StatusIcon.foo` | |
1374 | * and set immediately upon creation of the icon, it will also attempt to own this dbus name; | |
1375 | * this can be useful in sandboxed environments where a well-defined name is required. If | |
1376 | * additional icons are created, only the name given to the initial one will be used for dbus, | |
1377 | * though different names can still affect the sort order. This is set to the value of | |
1378 | * g_get_application_name() if no other name is provided. | |
1379 | */ | |
1380 | g_object_class_install_property (gobject_class, PROP_NAME, | |
1381 | g_param_spec_string ("name", | |
1382 | "The name of the icon for sorting purposes.", | |
1383 | NULL, | |
1384 | NULL, | |
1385 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); | |
1386 | ||
1387 | /** | |
1320 | 1388 | * XAppStatusIcon::button-press-event: |
1321 | 1389 | * @icon: The #XAppStatusIcon |
1322 | 1390 | * @x: The absolute x position to use for menu positioning |
1429 | 1497 | return; |
1430 | 1498 | } |
1431 | 1499 | |
1500 | if (name == NULL || name[0] == '\0') | |
1501 | { | |
1502 | g_warning ("Can't set icon the name to null or empty string"); | |
1503 | return; | |
1504 | } | |
1505 | ||
1432 | 1506 | g_clear_pointer (&icon->priv->name, g_free); |
1433 | 1507 | icon->priv->name = g_strdup (name); |
1434 | 1508 | |
1435 | 1509 | g_debug ("XAppStatusIcon set_name: %s", name); |
1436 | 1510 | |
1437 | if (icon->priv->skeleton) | |
1438 | { | |
1439 | xapp_status_icon_interface_set_name (icon->priv->skeleton, name); | |
1511 | if (icon->priv->interface_skeleton) | |
1512 | { | |
1513 | xapp_status_icon_interface_set_name (icon->priv->interface_skeleton, name); | |
1440 | 1514 | } |
1441 | 1515 | |
1442 | 1516 | /* Call this directly instead of in the update_fallback_icon() function, |
1473 | 1547 | |
1474 | 1548 | g_debug ("XAppStatusIcon set_icon_name: %s", icon_name); |
1475 | 1549 | |
1476 | if (icon->priv->skeleton) | |
1477 | { | |
1478 | xapp_status_icon_interface_set_icon_name (icon->priv->skeleton, icon_name); | |
1550 | if (icon->priv->interface_skeleton) | |
1551 | { | |
1552 | xapp_status_icon_interface_set_icon_name (icon->priv->interface_skeleton, icon_name); | |
1479 | 1553 | } |
1480 | 1554 | |
1481 | 1555 | update_fallback_icon (icon); |
1496 | 1570 | { |
1497 | 1571 | g_return_val_if_fail (XAPP_IS_STATUS_ICON (icon), FALLBACK_ICON_SIZE); |
1498 | 1572 | |
1499 | if (icon->priv->skeleton == NULL) | |
1573 | if (icon->priv->interface_skeleton == NULL) | |
1500 | 1574 | { |
1501 | 1575 | g_debug ("XAppStatusIcon get_icon_size: %d (fallback)", FALLBACK_ICON_SIZE); |
1502 | 1576 | |
1505 | 1579 | |
1506 | 1580 | gint size; |
1507 | 1581 | |
1508 | size = xapp_status_icon_interface_get_icon_size (icon->priv->skeleton); | |
1582 | size = xapp_status_icon_interface_get_icon_size (icon->priv->interface_skeleton); | |
1509 | 1583 | |
1510 | 1584 | g_debug ("XAppStatusIcon get_icon_size: %d", size); |
1511 | 1585 | |
1536 | 1610 | |
1537 | 1611 | g_debug ("XAppStatusIcon set_tooltip_text: %s", tooltip_text); |
1538 | 1612 | |
1539 | if (icon->priv->skeleton) | |
1540 | { | |
1541 | xapp_status_icon_interface_set_tooltip_text (icon->priv->skeleton, tooltip_text); | |
1613 | if (icon->priv->interface_skeleton) | |
1614 | { | |
1615 | xapp_status_icon_interface_set_tooltip_text (icon->priv->interface_skeleton, tooltip_text); | |
1542 | 1616 | } |
1543 | 1617 | |
1544 | 1618 | update_fallback_icon (icon); |
1568 | 1642 | |
1569 | 1643 | g_debug ("XAppStatusIcon set_label: '%s'", label); |
1570 | 1644 | |
1571 | if (icon->priv->skeleton) | |
1572 | { | |
1573 | xapp_status_icon_interface_set_label (icon->priv->skeleton, label); | |
1645 | if (icon->priv->interface_skeleton) | |
1646 | { | |
1647 | xapp_status_icon_interface_set_label (icon->priv->interface_skeleton, label); | |
1574 | 1648 | } |
1575 | 1649 | } |
1576 | 1650 | |
1597 | 1671 | |
1598 | 1672 | g_debug ("XAppStatusIcon set_visible: %s", visible ? "TRUE" : "FALSE"); |
1599 | 1673 | |
1600 | if (icon->priv->skeleton) | |
1601 | { | |
1602 | xapp_status_icon_interface_set_visible (icon->priv->skeleton, visible); | |
1674 | if (icon->priv->interface_skeleton) | |
1675 | { | |
1676 | xapp_status_icon_interface_set_visible (icon->priv->interface_skeleton, visible); | |
1603 | 1677 | } |
1604 | 1678 | |
1605 | 1679 | update_fallback_icon (icon); |
1782 | 1856 | } |
1783 | 1857 | |
1784 | 1858 | /** |
1859 | * xapp_status_icon_new_with_name: | |
1860 | * | |
1861 | * Creates a new #XAppStatusIcon instance and sets its name to %name. | |
1862 | * | |
1863 | * Returns: (transfer full): a new #XAppStatusIcon. Use g_object_unref when finished. | |
1864 | * | |
1865 | * Since: 1.6 | |
1866 | */ | |
1867 | XAppStatusIcon * | |
1868 | xapp_status_icon_new_with_name (const gchar *name) | |
1869 | { | |
1870 | return g_object_new (XAPP_TYPE_STATUS_ICON, | |
1871 | "name", name, | |
1872 | NULL); | |
1873 | } | |
1874 | ||
1875 | /** | |
1785 | 1876 | * xapp_status_icon_get_state: |
1786 | 1877 | * @icon: an #XAppStatusIcon |
1787 | 1878 | * |
1834 | 1925 | icon->priv->metadata = g_strdup (metadata); |
1835 | 1926 | g_free (old_meta); |
1836 | 1927 | |
1837 | if (icon->priv->skeleton) | |
1838 | { | |
1839 | xapp_status_icon_interface_set_metadata (icon->priv->skeleton, metadata); | |
1928 | if (icon->priv->interface_skeleton) | |
1929 | { | |
1930 | xapp_status_icon_interface_set_metadata (icon->priv->interface_skeleton, metadata); | |
1840 | 1931 | } |
1841 | 1932 | } |
1842 | 1933 |
46 | 46 | |
47 | 47 | |
48 | 48 | XAppStatusIcon *xapp_status_icon_new (void); |
49 | XAppStatusIcon *xapp_status_icon_new_with_name (const gchar *name); | |
49 | 50 | void xapp_status_icon_set_name (XAppStatusIcon *icon, const gchar *name); |
50 | 51 | void xapp_status_icon_set_icon_name (XAppStatusIcon *icon, const gchar *icon_name); |
51 | 52 | gint xapp_status_icon_get_icon_size (XAppStatusIcon *icon); |
26 | 26 | '--interface-prefix=' + sys.argv[1], |
27 | 27 | '--generate-c-code=' + os.path.join(sys.argv[4], sys.argv[2]), |
28 | 28 | '--c-namespace=XApp', |
29 | '--c-generate-object-manager', | |
29 | 30 | '--annotate', sys.argv[1], 'org.gtk.GDBus.C.Name', sys.argv[3], |
30 | 31 | sys.argv[5] |
31 | 32 | ]) |
166 | 166 | self.disco_button.set_label("Connect monitor") |
167 | 167 | |
168 | 168 | def on_icon_added(self, monitor, proxy): |
169 | name = proxy.get_name() | |
169 | name = proxy.get_name() + proxy.get_object_path() | |
170 | 170 | |
171 | 171 | self.indicators[name] = StatusWidget(proxy) |
172 | 172 | self.indicator_box.add(self.indicators[name]) |
175 | 175 | self.sort_icons() |
176 | 176 | |
177 | 177 | def on_icon_removed(self, monitor, proxy): |
178 | name = proxy.get_name() | |
178 | name = proxy.get_name() + proxy.get_object_path() | |
179 | 179 | |
180 | 180 | self.indicator_box.remove(self.indicators[name]) |
181 | 181 | self.indicators[name].disconnect_by_func(self.sort_icons) |