Codebase list xapp / f6db3f7
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
6 changed file(s) with 382 addition(s) and 327 deletion(s). Raw diff Collapse all Expand all
+0
-32
libxapp/g-codegen.py less more
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 ])
2020 #define MONITOR_NAME "org.x.StatusIconMonitor"
2121
2222 #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 "/"
2627
2728 #define STATUS_NOTIFIER_WATCHER_NAME "org.x.StatusNotifierWatcher"
2829 #define WATCHER_MAX_RESTARTS 2
5859 {
5960 GDBusConnection *connection;
6061
61 GHashTable *icons;
62 gchar *name;
62 GHashTable *object_managers;
6363
6464 guint owner_id;
6565 guint listener_id;
66 guint sn_watcher_id;
67
68 guint sn_watcher_retry_count;
69
7066 } XAppStatusIconMonitorPrivate;
7167
7268 struct _XAppStatusIconMonitor
7672
7773 G_DEFINE_TYPE_WITH_PRIVATE (XAppStatusIconMonitor, xapp_status_icon_monitor, G_TYPE_OBJECT)
7874
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;
9083
9184 g_object_get (object,
92 "g-name-owner", &name_owner,
93 "g-name", &proxy_name,
85 "name-owner", &owner,
86 "name", &name,
9487 NULL);
9588
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
147141 GError *error;
148 gchar *g_name;
142 gchar *name;
149143
150144 error = NULL;
151145
152 proxy = xapp_status_icon_interface_proxy_new_finish (res,
153 &error);
146 obj_mgr = xapp_object_manager_client_new_finish (res,
147 &error);
154148
155149 if (error)
156150 {
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);
158152 g_error_free (error);
159153 return;
160154 }
161155
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);
200212 }
201213 else
202214 {
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);
205219 }
206220
207221 static void
235249 /* the '.' at the end so we don't catch ourselves in this */
236250 if (g_str_has_prefix (str, STATUS_ICON_MATCH))
237251 {
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);
240254 }
241255 }
242256
249263 {
250264 XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self);
251265
252
253 g_debug("XAppStatusIconMonitor: looking for status icons on the bus");
266 g_debug("XAppStatusIconMonitor: looking for status icon apps on the bus");
254267
255268 /* If there are no monitors (applets) already running when this is set up,
256269 * this won't find anything. The XAppStatusIcons will be in fallback mode,
289302 }
290303
291304 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
328305 name_owner_changed (GDBusConnection *connection,
329306 const gchar *sender_name,
330307 const gchar *object_path,
343320
344321 g_variant_get (parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
345322
346 if (old_owner[0] != '\0')
347 {
348 status_icon_name_vanished (self, name);
349 }
350
351323 if (new_owner[0] != '\0')
352324 {
353 status_icon_name_appeared (self, name, new_owner);
354 }
355 }
356
325 add_object_manager_for_name (self, name);
326 }
327 }
357328
358329 static void
359330 add_name_listener (XAppStatusIconMonitor *self)
360331 {
361332 XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self);
362333
363 g_debug ("XAppStatusIconMonitor: Adding NameOwnerChanged listener for status icons");
334 g_debug ("XAppStatusIconMonitor: Adding NameOwnerChanged listener for status icon apps");
364335
365336 priv->listener_id = g_dbus_connection_signal_subscribe (priv->connection,
366337 "org.freedesktop.DBus",
392363 {
393364 XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data);
394365
395 g_debug ("XAppStatusIconMonitor: name acquired on dbus");
366 g_debug ("XAppStatusIconMonitor: Name owned on bus: %s", name);
396367
397368 add_name_listener (self);
398369 find_and_add_icons (self);
407378 XAppStatusIconMonitor *self = XAPP_STATUS_ICON_MONITOR (user_data);
408379 XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self);
409380
410 g_debug ("XAppStatusIconMonitor: session bus connection acquired");
381 g_debug ("XAppStatusIconMonitor: Connected to bus: %s", name);
411382
412383 priv->connection = connection;
413384 }
416387 connect_to_bus (XAppStatusIconMonitor *self)
417388 {
418389 XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self);
419
390 gchar *valid_app_name, *owned_name;
420391 static gint unique_id = 0;
421392
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);
427398
428399 priv->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
429 owner_name,
400 owned_name,
430401 G_DBUS_CONNECTION_FLAGS_NONE,
431402 on_bus_acquired,
432403 on_name_acquired,
434405 self,
435406 NULL);
436407
437 g_free(owner_name);
408 g_free(owned_name);
438409 }
439410
440411 static void
442413 {
443414 XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (self);
444415
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);
451418
452419 connect_to_bus (self);
453420 }
468435 priv->listener_id = 0;
469436 }
470437
438 if (priv->object_managers != NULL)
439 {
440 g_hash_table_unref (priv->object_managers);
441 priv->object_managers = NULL;
442 }
443
471444 if (priv->owner_id > 0)
472445 {
473446 g_bus_unown_name(priv->owner_id);
474447 priv->owner_id = 0;
475448 }
476449
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
483450 g_clear_object (&priv->connection);
484451 }
485
486 g_free (priv->name);
487 g_clear_pointer (&priv->icons, g_hash_table_unref);
488452
489453 G_OBJECT_CLASS (xapp_status_icon_monitor_parent_class)->dispose (object);
490454 }
538502 G_TYPE_NONE, 1, XAPP_TYPE_STATUS_ICON_INTERFACE_PROXY);
539503 }
540504
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
541530 /**
542531 * xapp_status_icon_monitor_list_icons:
543532 * @monitor: a #XAppStatusIconMonitor
552541 xapp_status_icon_monitor_list_icons (XAppStatusIconMonitor *monitor)
553542 {
554543 g_return_val_if_fail (XAPP_IS_STATUS_ICON_MONITOR (monitor), NULL);
544 GList *ret = NULL;
555545
556546 XAppStatusIconMonitorPrivate *priv = xapp_status_icon_monitor_get_instance_private (monitor);
557547
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;
559553 }
560554
561555 /**
1919 #define FDO_DBUS_NAME "org.freedesktop.DBus"
2020 #define FDO_DBUS_PATH "/org/freedesktop/DBus"
2121
22 #define ICON_PATH "/org/x/StatusIcon"
22 #define ICON_BASE_PATH "/org/x/StatusIcon"
23 #define ICON_SUB_PATH (ICON_BASE_PATH "/Icon")
2324 #define ICON_NAME "org.x.StatusIcon"
2425
2526 #define STATUS_ICON_MONITOR_MATCH "org.x.StatusIconMonitor"
2930 #define MAX_SANE_ICON_SIZE 96
3031 #define FALLBACK_ICON_SIZE 24
3132
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;
3340
3441 enum
3542 {
4956 PROP_PRIMARY_MENU,
5057 PROP_SECONDARY_MENU,
5158 PROP_ICON_SIZE,
59 PROP_NAME,
5260 N_PROPERTIES
5361 };
5462
6674 */
6775 typedef struct
6876 {
69 XAppStatusIconInterface *skeleton;
7077 GDBusConnection *connection;
78 XAppStatusIconInterface *interface_skeleton;
79 XAppObjectSkeleton *object_skeleton;
7180
7281 GCancellable *cancellable;
7382
8594 gint icon_size;
8695 gchar *metadata;
8796
88 guint owner_id;
8997 guint listener_id;
9098
9199 gint fail_counter;
102110
103111 static void refresh_icon (XAppStatusIcon *self);
104112 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);
106114
107115 static void
108116 cancellable_reset (XAppStatusIcon *self)
265273
266274 if (icon->priv->state == XAPP_STATUS_ICON_STATE_NATIVE)
267275 {
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);
269277 }
270278
271279 g_signal_handlers_disconnect_by_func (widget, primary_menu_unmapped, icon);
282290
283291 if (icon->priv->state == XAPP_STATUS_ICON_STATE_NATIVE)
284292 {
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);
286294 }
287295
288296 g_signal_handlers_disconnect_by_func (widget, secondary_menu_unmapped, icon);
327335 {
328336 if (self->priv->state == XAPP_STATUS_ICON_STATE_NATIVE)
329337 {
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);
331339 }
332340
333341 g_signal_connect (gtk_widget_get_toplevel (GTK_WIDGET (menu)),
340348 {
341349 if (self->priv->state == XAPP_STATUS_ICON_STATE_NATIVE)
342350 {
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);
344352 }
345353
346354 g_signal_connect (gtk_widget_get_toplevel (GTK_WIDGET (menu)),
728736
729737 g_clear_object (&self->priv->gtk_status_icon);
730738
731 g_object_set (G_OBJECT (priv->skeleton),
739 g_object_set (G_OBJECT (priv->interface_skeleton),
732740 "name", priv->name,
733741 "label", priv->label,
734742 "icon-name", priv->icon_name,
737745 "metadata", priv->metadata,
738746 NULL);
739747
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));
741749 }
742750
743751 static void
769777 { "handle-scroll", handle_scroll_method }
770778 };
771779
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
772812 static gboolean
773813 export_icon_interface (XAppStatusIcon *self)
774814 {
775 GError *error = NULL;
776815 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 {
780821 return TRUE;
781822 }
782823
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);
802835
803836 for (i = 0; i < G_N_ELEMENTS (skeleton_signals); i++) {
804837 SkeletonSignal sig = skeleton_signals[i];
805838
806 g_signal_connect (self->priv->skeleton,
839 g_signal_connect (self->priv->interface_skeleton,
807840 sig.signal_name,
808841 G_CALLBACK (sig.callback),
809842 self);
815848 static void
816849 connect_with_status_applet (XAppStatusIcon *self)
817850 {
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 }
832885
833886 g_free(owner_name);
834887 }
895948
896949 g_debug ("XAppStatusIcon: falling back to GtkStatusIcon");
897950
898 tear_down_dbus (self);
951 remove_icon_path_from_bus (self);
899952
900953 // Make sure there wasn't already one
901954 g_clear_object (&self->priv->gtk_status_icon);
9701023
9711024 if (found && export_icon_interface (self))
9721025 {
973 if (self->priv->owner_id > 0)
1026 if (name_owner_id > 0)
9741027 {
975 g_debug ("XAppStatusIcon: We already exist on the bus, syncing icon properties");
9761028 sync_skeleton (self);
9771029 }
9781030 else
10641116 return;
10651117 }
10661118
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);
10741120 }
10751121
10761122 static void
10771123 refresh_icon (XAppStatusIcon *self)
10781124 {
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");
10821128
10831129 cancellable_reset (self);
10841130
11101156 case PROP_ICON_SIZE:
11111157 XAPP_STATUS_ICON (object)->priv->icon_size = CLAMP (g_value_get_int (value), 0, MAX_SANE_ICON_SIZE);
11121158 break;
1159 case PROP_NAME:
1160 xapp_status_icon_set_name (XAPP_STATUS_ICON (object), g_value_get_string (value));
1161 break;
11131162 default:
11141163 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
11151164 break;
11351184 case PROP_ICON_SIZE:
11361185 g_value_set_int (value, icon->priv->icon_size);
11371186 break;
1187 case PROP_NAME:
1188 g_value_set_string (value, icon->priv->name);
1189 break;
11381190 default:
11391191 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
11401192 break;
11461198 {
11471199 self->priv = xapp_status_icon_get_instance_private (self);
11481200
1149 self->priv->name = g_strdup_printf("%s", g_get_application_name());
1201 self->priv->name = g_strdup (g_get_application_name());
1202
11501203 self->priv->state = XAPP_STATUS_ICON_STATE_NO_SUPPORT;
11511204 self->priv->icon_size = FALLBACK_ICON_SIZE;
11521205 self->priv->icon_name = g_strdup (" ");
11601213 }
11611214
11621215 static void
1163 tear_down_dbus (XAppStatusIcon *self)
1216 remove_icon_path_from_bus (XAppStatusIcon *self)
11641217 {
11651218 g_return_if_fail (XAPP_IS_STATUS_ICON (self));
11661219
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);
11821232 }
11831233 }
11841234
12081258 self->priv->gtk_status_icon = NULL;
12091259 }
12101260
1211 tear_down_dbus (self);
1261 remove_icon_path_from_bus (self);
12121262
12131263 if (self->priv->listener_id > 0)
12141264 {
12151265 g_dbus_connection_signal_unsubscribe (self->priv->connection, self->priv->listener_id);
1266 self->priv->listener_id = 0;
12161267 }
12171268
12181269 g_clear_object (&self->priv->connection);
13171368 G_PARAM_READWRITE));
13181369
13191370 /**
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 /**
13201388 * XAppStatusIcon::button-press-event:
13211389 * @icon: The #XAppStatusIcon
13221390 * @x: The absolute x position to use for menu positioning
14291497 return;
14301498 }
14311499
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
14321506 g_clear_pointer (&icon->priv->name, g_free);
14331507 icon->priv->name = g_strdup (name);
14341508
14351509 g_debug ("XAppStatusIcon set_name: %s", name);
14361510
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);
14401514 }
14411515
14421516 /* Call this directly instead of in the update_fallback_icon() function,
14731547
14741548 g_debug ("XAppStatusIcon set_icon_name: %s", icon_name);
14751549
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);
14791553 }
14801554
14811555 update_fallback_icon (icon);
14961570 {
14971571 g_return_val_if_fail (XAPP_IS_STATUS_ICON (icon), FALLBACK_ICON_SIZE);
14981572
1499 if (icon->priv->skeleton == NULL)
1573 if (icon->priv->interface_skeleton == NULL)
15001574 {
15011575 g_debug ("XAppStatusIcon get_icon_size: %d (fallback)", FALLBACK_ICON_SIZE);
15021576
15051579
15061580 gint size;
15071581
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);
15091583
15101584 g_debug ("XAppStatusIcon get_icon_size: %d", size);
15111585
15361610
15371611 g_debug ("XAppStatusIcon set_tooltip_text: %s", tooltip_text);
15381612
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);
15421616 }
15431617
15441618 update_fallback_icon (icon);
15681642
15691643 g_debug ("XAppStatusIcon set_label: '%s'", label);
15701644
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);
15741648 }
15751649 }
15761650
15971671
15981672 g_debug ("XAppStatusIcon set_visible: %s", visible ? "TRUE" : "FALSE");
15991673
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);
16031677 }
16041678
16051679 update_fallback_icon (icon);
17821856 }
17831857
17841858 /**
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 /**
17851876 * xapp_status_icon_get_state:
17861877 * @icon: an #XAppStatusIcon
17871878 *
18341925 icon->priv->metadata = g_strdup (metadata);
18351926 g_free (old_meta);
18361927
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);
18401931 }
18411932 }
18421933
4646
4747
4848 XAppStatusIcon *xapp_status_icon_new (void);
49 XAppStatusIcon *xapp_status_icon_new_with_name (const gchar *name);
4950 void xapp_status_icon_set_name (XAppStatusIcon *icon, const gchar *name);
5051 void xapp_status_icon_set_icon_name (XAppStatusIcon *icon, const gchar *icon_name);
5152 gint xapp_status_icon_get_icon_size (XAppStatusIcon *icon);
2626 '--interface-prefix=' + sys.argv[1],
2727 '--generate-c-code=' + os.path.join(sys.argv[4], sys.argv[2]),
2828 '--c-namespace=XApp',
29 '--c-generate-object-manager',
2930 '--annotate', sys.argv[1], 'org.gtk.GDBus.C.Name', sys.argv[3],
3031 sys.argv[5]
3132 ])
166166 self.disco_button.set_label("Connect monitor")
167167
168168 def on_icon_added(self, monitor, proxy):
169 name = proxy.get_name()
169 name = proxy.get_name() + proxy.get_object_path()
170170
171171 self.indicators[name] = StatusWidget(proxy)
172172 self.indicator_box.add(self.indicators[name])
175175 self.sort_icons()
176176
177177 def on_icon_removed(self, monitor, proxy):
178 name = proxy.get_name()
178 name = proxy.get_name() + proxy.get_object_path()
179179
180180 self.indicator_box.remove(self.indicators[name])
181181 self.indicators[name].disconnect_by_func(self.sort_icons)