blueman-project/blueman

Blueman Tray is not using StatusNotifierItem correctly

Closed this issue · 4 comments

blueman: 2.4.3
BlueZ:
Distribution: Fedora
Desktop environment: Sway

Hello,

I'm writing an integration which uses the StatusNotifier DBus protocol to display tray icons.

I believe Blueman is not using this protocol correctly.

Blueman seems to be registering its StatusNotifierItem via it's DBUS object name, and not the bus name.

For example:

** (way-shell:67420): DEBUG: 14:37:29.902: status_notifier_service.c:on_handle_register_item() called: /org/blueman/sni

This makes it impossible to find the bus name.

By contract this is how DropBox registers its StatusNotifierItem

** (way-shell:71357): DEBUG: 14:55:53.290: status_notifier_service.c:on_handle_register_item() called: org.kde.StatusNotifierItem-7-1

With a /StatusNotifierItem object at the root of the bus

node /StatusNotifierItem {
    interface org.kde.StatusNotifierItem {
      methods:

Which is aligned to the spec

Register a StatusNotifierItem into the StatusNotifierWatcher, in the form of its full name on the session bus, for instance org.freedesktop.StatusNotifierItem-4077-1. A StatusNotifierItem instance must be registered to the watcher in order to be noticed from both the watcher and the StatusNotifierHost instances. If the registered StatusNotifierItem goes away from the session bus, the StatusNotifierWatcher should automatically notice it and remove it from the list of registered services.

Is this by design?

I don't know a lot about the StatusNotifier stuff but I had a quick look at what Pithos does and replicated it in blueman, which works for me on plasma. Does this conform better with how you interpret the spec @ldelossa ?

@cschramm did all of the hard work and research on this so they hopefully can comment on the design part.

ps: XFCE and Mate work fine for me as well.

diff --git a/blueman/main/indicators/StatusNotifierItem.py b/blueman/main/indicators/StatusNotifierItem.py
index 3ab75ad59..a2387a661 100644
--- a/blueman/main/indicators/StatusNotifierItem.py
+++ b/blueman/main/indicators/StatusNotifierItem.py
@@ -101,7 +101,7 @@ class StatusNotifierItemService(DbusService):
     ItemIsMenu = False
 
     def __init__(self, tray: BluemanTray, icon_name: str) -> None:
-        super().__init__(None, "org.kde.StatusNotifierItem", "/org/blueman/sni", Gio.BusType.SESSION,
+        super().__init__(None, "org.kde.StatusNotifierItem", "/StatusNotifierItem", Gio.BusType.SESSION,
                          {"Category": "s", "Id": "s", "IconName": "s", "Status": "s", "Title": "s",
                           "ToolTip": "(sa(iiay)ss)", "Menu": "o", "ItemIsMenu": "b"})
         self.add_method("Activate", ("i", "i"), "", lambda x, y: tray.activate_status_icon())
@@ -151,7 +151,7 @@ class StatusNotifierItem(IndicatorInterface):
         try:
             Gio.bus_get_sync(Gio.BusType.SESSION).call_sync(
                 self._SNI_BUS_NAME, "/StatusNotifierWatcher", self._SNI_INTERFACE_NAME,
-                "RegisterStatusNotifierItem", GLib.Variant("(s)", ("/org/blueman/sni",)),
+                "RegisterStatusNotifierItem", GLib.Variant("(s)", ("org.blueman.Tray",)),
                 None, Gio.DBusCallFlags.NONE, -1)
             watcher_expected = True
         except GLib.Error:

You diff here is definitely what I would expect if Blueman was conforming to the freedesktop Spec. Altho, the name you use on the bus should be similar to "org.kde.StatusNotifierItem-{pid}-{id}". This makes it so implementations can watch for just this well formed bus name. This matters a bit less, since you give the bus name right to the statusnotifier displayer, but that would be closer to the spec.

What Ive been finding is theres 3 major ways apps have been exposing their SNI.

  1. By sending the /org/ayatana/{app}/StatusNotifierItem object
  2. By sending an arbitrary object (this is what blueman does)
  3. By sending the bus name with the object at root

It looks like, implementations have just been programmed to handle these cases. However, its far nicer as a developer to deal with case 3, which aligns to the freedesktop spec.

I was wrong when I mentioned its "impossible to find the bus name". This is not true, as you can always lookup the bus name for a remote call into your dbus service.

Anyway, yes that diff looks better to me, what I would expect in the freedesktop spec was being followed.

I cannot recall all details from three years ago, but #1382 (comment) describes the situation rather good:

  • libappindicator and Ayatana pass an object path and use the sender of the registration call as the service to talk to.
  • KNotifications passes a service name and uses /StatusNotifierItem as the object path.
  • The specification adopts KNotifications' service name argument but does not specify an object path.
  • All implementations that I looked at support both the appindicator and the KNotifications variants. Otherwise they would have limited compatibility.

I do not understand how the specification should work without an agreed object path like /StatusNotifierItem. Also, that does not seem very reasonable, as it e.g. limits things to one StatusNotifierItem per service. The patch mainly means to replace the appindicator flavor with that of KNotifications. Yes, it's closer to the specification, as a service name gets passed instead of an object name, but the specification just does not work due to the lack of an object path.

As far as I can tell, things did not develop (and I do not expect them to), so applications are left with choosing the appindicator or the KNotifications flavor and hosts need to support both.

Thank you @cschramm

I think that explains the situation well. Now I understand there are multiple supported specs here. I dont feel strongly about keeping this issue open. Its a shame we have varying specs to deal with, but no issue here since one was picked and stuck with.