#264 Work on a new appindicator protocol
Closed: Deferred to upstream 11 months ago by catanzaro. Opened 2 years ago by mclasen.

This is a follow-up from https://pagure.io/fedora-workstation/issue/246

When we discussed this ticket in the WG meeting on 01-11-2022, the sentiment
was that we should have some idea for how to support app indicators / status notifiers upstream before we go the "just use the extension" route. Since the
existing appindicator protocol is deemed unacceptable upstream, we need a
suggestion for a protocol that would, even if we end up supporting the existing appindicator protocol with a proxy (or directly).

Here is some prior work by Patrick on this: https://blog.tingping.se/2019/09/07/how-to-design-a-modern-status-icon.html

The concrete task here is to form a working group for this task, and report back with results.

Candidates for such a working group: Matthias, Florian, somebody from the KDE side, somebody from Canonical


Patrick's blog post is missing a reference to https://ayatanaindicators.github.io/code/, which is a fifth incompatible indicator spec, but I understand this one has not achieved much adoption anywhere. Our goal should be to design a sixth incompatible spec to replace the first five, in the true spirit of https://xkcd.com/927/.

A contributor has provided us with a draft spec based on the KDE status notifiers as a starting point. There are a couple TODOs regarding icon and menu serialization, most importantly how to build a GMenu from Qt. If Canonical or KDE don't want to change how the menus work, then we should be willing to compromise on the menus first, because messy menus are more a wart than a blocker. (I have not investigated libdbusmenu to see why it is so disliked.)

Removing X11-isms and removing sandboxing mistakes like "app must own entire org.kde D-Bus namespace to create an indicator" or "app must use PID namespace of host system" should be the main priorities.

<?xml version="1.0"?>
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
  <!--
      This spec describes a way for applications to export a status icon
      and an associated menu.
      How this is used:
      1. Application creates a dbus object implementing the org.freedesktop.StatusIcon interface and exports it.
      2. Application watches for the bus name org.freedesktop.portal.StatusIconService
      3. Whenever it appears it subscribes to the StatusIconStateChanged signal
      4. It calls AddStatusIcon()
      5. Based on the StatusIconStateChanged changes, and the bus name disappearing, the application will always
         be up to date on the visibility of the status icon
      THIS IS A DRAFT!
      Notable differences from the org.kde.StatusNotifier specs:
      - Category has been removed. In practice these were not used in a meaningful way?
      - WindowId has been removed. This was an X11 detail.
      - IconThemePath has been removed. Filesystem paths aren't useful for sandboxed applications.
      - All New*() signals have been removed. org.freedesktop.DBus.Properties handles property change notifications.
      - Status was turned into an enum instead of strings and more clearly defined as the State property.
      - Activate/SecondaryActivate no longer has x,y arguments: These are details that don't make sense without X11.
      - All Attention properties removed: This has no distinction and you can change the normal Icon at any time.
      - ToolTip was simplified to text only.
      - Scroll removes orientation argument: Horizontal scrolling isn't commonly handled or supported.
      - ContextMenu method is removed: This only makes sense on X11.
      - Menu property changed to org.gtk.Menus: This is more simple than DBusMenu.
      - No well known dbus names are recommended for exporting your status icon. This means it works in a sandbox.
        The `org.kde.StatusNotifierItem-PID-ID` naming was broken on multiple levels:
        - PID's are useless in pid-namespaced sandboxes
          Real world apps are broken here, they all try to own the PID `2` because they are all the same in every sandbox
        - Bus name ownership is explicitly forbidden unless a permission is granted to the flatpak
          Even worse `org.kde.StatusNotifierItem-PID-ID` is not namespaced so you must grant ownership permissions to all of `org.kde.*` for it to work in flatpak.
          This means *all* KDE flatpaks can pretend to be *any* KDE service. All security is currently lost.
        - The watchers bus name is hardcoded to be `org.kde.StatusNotifierWatcher`. DBus talk permissions are forbidden to this namespace unless explicitly granted.
      - The Id property is removed. This is now passed when you register the status icon. It doesn't make sense to be a
        changable property.
      - All visibility tracking is kept to one StatusIconStateChanged signal. Instead of tracking if your icon was
        registered, unregistered, and if the StatusNotifierHost is registered or not.
  -->

  <!--
      org.freedesktop.StatusIcon:
      @short_description: Interface for application exposed status icons
   -->
  <interface name="org.freedesktop.StatusIcon">
    <!-- Descriptive title for the application, this MAY be shown by the host -->
    <property name="Title" type="s" access="read"/>
    <!-- Tooltip text to show on hover, this MAY be shown by the host -->
    <property name="ToolTip" type="s" access="read"/>
    <!-- Name referring to the icon to show as-per icon-theme-spec -->
    <property name="IconName" type="s" access="read"/>
    <!-- Name referring to an icon to overlay as-per icon-theme-spec -->
    <property name="OverlayIconName" type="s" access="read"/>
    <!-- Item has a valid Menu property -->
    <property name="ItemIsMenu" type="b" access="read"/>
    <!-- Exported org.gtk.Menus object
         https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI#org.gtk.Menus
         TODO: This needs to have a good Qt story.
               Something exists here: https://github.com/KDE/plasma-workspace/tree/master/gmenu-dbusmenu-proxy
      -->
    <property name="Menu" type="o" access="read"/>

    <!-- TODO: Binary formats for icons. Note these must be handled safely by the host and must handle scaling. -->

    <!--
        State: The state of the StatusIcon
        Currently defined states are:
        <simplelist>
          <member>0: HIDDEN</member>
          <member>1: VISIBLE</member>
        </simplelist>
        When set to HIDDEN the host MUST not show the status icon.
        When set to VISIBLE the host MUST show the status icon.
    -->
    <property name="State" type="u" access="read"/>

    <!--
        Activate: Emitted when the icon received a primary click.
        QUESTION: Single and double click are inconsistant?
    -->
    <method name="Activate"/>
    <!--
        SecondaryActivate: Emitted when the icon received a secondary click.
        QUESTION: Should we actually keep this, it seems intended for showing your own menus
                  which can't be done.
    -->
    <method name="SecondaryActivate"/>
    <!--
        Scroll: Emitted on mouse scroll while over the icon.
    -->
    <method name="Scroll">
        <arg name="delta" type="i" direction="in"/>
    </method>
  </interface>


  <!--
      org.freedesktop.portal.StatusIconService:
      @short_description: Portal interface that registers status icons.
   -->
  <interface name="org.freedesktop.portal.StatusIconService">
    <!--
        Internally how this is implemented is undefined.
        It would be very possible for `xdg-desktop-portal-kde` to simply
        use the existing infrastructure for status icons. This is effectively
        the old StatusNotifierWatcher, the StatusNotifierHost is still external.
        The menu translation really being the only tricky part if that changes.
        GNOME and others would need its own internal interface for this.
     -->

    <!--
        AddStatusIcon: Registers a new status icon.
        @id: Unique identifier for the icon
        @path: The path for the exported icon
    -->
    <method name="AddStatusIcon">
      <arg type="s" name="id" direction="in"/>
      <arg type="o" name="path" direction="in"/>
    </method>

    <!--
        RemoveStatusIcon: Removes status icon.
        @id: Unique identifier for the icon
    -->
    <method name="RemoveStatusIcon">
      <arg type="s" name="id" direction="in"/>
    </method>

    <!--
        StatusIconStateChanged:
        @app_id: App id of the application
        @id: the application-provided ID for the status icon
        @state: The state of the status icon
        Send to the application when the visibility of a status
        icon changes.
        Currently defined states are:
        <simplelist>
          <member>0: HIDDEN</member>
          <member>1: VISIBLE</member>
        </simplelist>
    -->
    <signal name="StatusIconStateChanged">
      <arg type="s" name="app_id"/>
      <arg type="s" name="id"/>
      <arg type="u" name="state"/>
    </signal>

    <!--
        ActionInvoked:
        @app_id: App id of the application
        @id: the application-provided ID for the status icon
        @action: the name of the action
        @parameter: array which will contain the target parameter
          for the action, if one was specified
        Send to the application when a non-exported action is
        activated.
    -->
    <signal name="ActionInvoked">
      <arg type="s" name="app_id"/>
      <arg type="s" name="id"/>
      <arg type="s" name="action"/>
      <arg type="av" name="parameter"/>
    </signal>
  </interface>
</node>

Our goal should be to design a sixth incompatible spec to replace the first five, in the true spirit of https://xkcd.com/927/.

It might be pragmatic to couch this as a backwards-incompatible update to one of the existing standards, rather than an entirely new thing (even though it really is).

Candidates for such a working group: Matthias, Florian, somebody from the KDE side, somebody from Canonical

I suggest we invite Ayatana and xapp to each send a developer. That would cover every current status icon implementation.

From the KDE side, at least @ngraham has expressed interest in helping. @apol may be interested too, though he's a bit busy right now.

I think it'd be wise to discuss this somewhere agnostic like xdg@lists.freedesktop.org

I think it'd be wise to discuss this somewhere agnostic like xdg@lists.freedesktop.org

Once we have a draft spec, yes, we'd probably want to do that. This doesn't even count as a draft yet.

Metadata Update from @ngompa:
- Issue tagged with: experience

2 years ago

I think it'd be wise to discuss this somewhere agnostic like xdg@lists.freedesktop.org

I agree it would be nice to move this to freedesktop.org somehow. That said, it shouldn't require joining a mailing list. Maybe an issue report at https://gitlab.freedesktop.org/xdg/xdg-specs/-/issues would be a good place to work?

Things that are missing from the draft:

An intro: There needs to be some text that explains what this spec is about, the scope and
relevant parties. The initial comment is a good start.

UX and behavior guidelines:

  • What can users of the API expect from compositors implementing it? Does the icon have to be permanently visible on screen, or is it fine for the compositor to e,g, hide it away in some drawer?
  • How should menus be exposed ? Does it have to be right click on the icon?
  • What are the expectations for the client ? Is it ok to ignore the activate call, or should the app provide some clearly visible user feedback?
  • How is this icon overlaying supposed to work ? Are the icons the same size ? What if they aren't?

Lacking these is a big part of why the original spec isn't adequate.

Information about required and optional parts, and acceptable use of the api:

  • What happens if I leave the icon-name property empty?
  • Is it ok to change the icon-name after registering?
  • Can I add or remove menu items or submenus?
  • What does HIDDEN vs VISIBLE indicate, exactly? If the statusicons are packed into a drawer or submenu, does that count as HIDDEN until the drawer is opened?

Consistency with other specs, and internally:

  • For notifications, icons are generally sent as image data. Should that be done here too?
  • We already have dbus interfaces for activating actions - why does this spec need to add another?
  • What is the point of the unique ID? Why is the path not sufficient?
  • The Scroll handling seems inadequate. Scroll events come in different flavors. The may be discrete, or they may have x/y deltas

I think it'd be wise to discuss this somewhere agnostic like xdg@lists.freedesktop.org

I agree it would be nice to move this to freedesktop.org somehow. That said, it shouldn't require joining a mailing list. Maybe an issue report at https://gitlab.freedesktop.org/xdg/xdg-specs/-/issues would be a good place to work?

That makes sense to me.

Just some comments that can get added back into the draft:

How is this icon overlaying supposed to work ? Are the icons the same size ? What if they aren't?

Maybe it is worth just removing this property. In practice applications can often include premade icons with overlays and in the advanced case its not hard to composite them client side. This removes any implementation doubts of how it would look.

Is it ok to change the icon-name after registering?

The pattern for all trays is they can change the icon whenever. This does have some questions about security and performance (the host should cache a few icons in case it changes frequently?).

Can I add or remove menu items or submenus?

Both GMenu and DBusmenu support dynamically changing menus. Hosts should support this.

What does HIDDEN vs VISIBLE indicate, exactly? If the statusicons are packed into a drawer or submenu, does that count as HIDDEN until the drawer is opened?

So this is overloaded by two ideas and maybe shouldn't be:

Previously it was possible to set a statusnotifier to "Active" or "Passive". I found this wording more clear but I guess not clear enough. The idea is just that a tray can be registered but set to not be shown at all. Maybe this is a mis-feature. Toggling on and off shouldn't be common and the fact a tray exists has meaning (an application is effectively running in the background).

I also used this property to indicate that the host has finally shown the icon in their tray. As-in the application can start making assumptions that the user sees it and its safe to do something like hide a main window.

For notifications, icons are generally sent as image data. Should that be done here too?

I wouldn't say that is true, I believe by icon-name is the most common. I do think sending data should be supported and often recommended.

I've updated this to be the same serialized format we use for org.freedesktop.portal.Notifications.

We already have dbus interfaces for activating actions - why does this spec need to add another?

org.freedesktop.Portal.Notifications already has this pattern. It exists for private actions or applications that don't support exporting actions, as I understand it.

What is the point of the unique ID? Why is the path not sufficient?

Good idea :thumbsup:.

The Scroll handling seems inadequate. Scroll events come in different flavors. The may be discrete, or they may have x/y deltas

As implemented in GNOME. It is either +1 for each scroll event up and -1 for each scroll event down.

UX and behavior guidelines:

On that broad topic my thoughts:

  • Left click always activates the Activate signal. (We should actually get rid of SecondaryActivate as the comment above says). In GNOME currently this is emitted from double left click and middle click. Double clicking is terrible as the first click opens the menu.
  • Middle click can continue to work as Activate.
  • Right click either does nothing or renders a pop-up menu.
    • Menus must support: submenus, toggle menus, and radio menus all with just text labels. I think we should avoid all other features. DBusmenu is designed to support effectively everything since its original purpose was to move complex application menubars around, but we only need a subset.
  • Icons
    • I'm not certain of sizes but I think we should limit scope to 24/32/48px icons*.
    • *We must expose DPI scaling though. Maybe the host service exposes this and clients do the right thing?
    • Handling of symbolic icons needs to be done on the host.

Thanks, all of that sounds right to me

Let's move upstream work to: https://gitlab.freedesktop.org/xdg/xdg-specs/-/issues/84

This issue should remain open for downstream tracking purposes.

Metadata Update from @aday:
- Issue set to the milestone: Fedora 37

2 years ago

We discussed this issue as part of our F37 planning, and it seemed that there was more to discuss.

Metadata Update from @aday:
- Issue tagged with: meeting

2 years ago

I personally think that Fedora could follow the Ubuntu and other distros' approach and consider adding the "gnome-shell-extension-appindicator" extension to base Workstation installation and enabling it by default until the new xdg spec is ready and implemented by upstream (GNOME and KDE). This would make the end user experience much better for the time before the new spec is ready and adopted by Fedora and other mainstream distros.

The working group has discussed this issue a couple of times recently. At the moment we're waiting on someone to step up to work on the new protocol.

This is unlikely to happen for F37, so pushing to F38.

Metadata Update from @aday:
- Issue untagged with: meeting
- Issue set to the milestone: Fedora 38 (was: Fedora 37)

2 years ago

Metadata Update from @catanzaro:
- Issue assigned to catanzaro

2 years ago

Metadata Update from @catanzaro:
- Issue tagged with: pending-action

2 years ago

I'm going to put an ultimatum here, because I'm sick of this being dragged out and jerked around: if we don't have this resolved for GNOME 45, I will reopen #246 and proceed with shipping the appindicator extension.

It is not acceptable that we don't prioritize fixing a huge UX hole in Fedora Workstation.

I do know that the StatusNotifier could use some refreshing, especially for flatpak integration. I'll be staying in LAS and the "shell and display hackfest" next month. Would it be useful to sit down and see which quirks would need addressing?

It would be very much appreciated focussing the parts that are wrong as @catanzaro said:

Removing X11-isms and removing sandboxing mistakes like "app must own entire org.kde D-Bus namespace to create an indicator" or "app must use PID namespace of host system" should be the main priorities.

We should refrain from rewriting the protocol as if it was all a new concept as it will break a number of applications that are working and relying on it just fine now.

From talking to Campbell Jones last week (from Budgie Desktop) who recently implemented the spec from scratch for Budgie 10.8, the only significant flaws he saw in the standard are:

  • Non-usage of the fdo listener (everyone uses the kde one, even though Budgie and KDE support both of them)
  • Support for raster images/pixmaps (everything should be SVG so scaling is cheap)
  • Defaulting to icon paths instead of icon names
  • No awareness of PID mappings to deal with sandboxed applications (Flatpaks/Snaps)
  • No specification of the menu bitstream (nobody knows what GMenu is)

He considered the rest of the standard pretty well-thought and worth keeping as-is.

All in all, I consider these minor fixes that can be made as a v2 of the existing SNI standard.

cc: @joshstrobl

I do know that the StatusNotifier could use some refreshing, especially for flatpak integration. I'll be staying in LAS and the "shell and display hackfest" next month. Would it be useful to sit down and see which quirks would need addressing?

Yes, that would be useful. However, we don't have budget for me to go to LAS this year. So probably best to tackle this online, unless you can find others going to LAS who want to collaborate.

Non-usage of the fdo listener (everyone uses the kde one, even though Budgie and KDE support both of them)
Support for raster images/pixmaps (everything should be SVG so scaling is cheap)
Defaulting to icon paths instead of icon names
No awareness of PID mappings to deal with sandboxed applications (Flatpaks/Snaps)
No specification of the menu bitstream (nobody knows what GMenu is)

Much of that is similar to GNOME's list of concerns. Probably best to keep the technical details in the upstream issue https://gitlab.freedesktop.org/xdg/xdg-specs/-/issues/84.

We should refrain from rewriting the protocol as if it was all a new concept as it will break a number of applications that are working and relying on it just fine now.

BTW support for existing applications is a red line for GNOME. We'll only support apps that update to the new standard and will not accept compatibility with existing applications.

There is a lot of discussion in the issue report and draft spec.

BTW support for existing applications is a red line for GNOME.

This is not a red line for Fedora, though. So if you block it in GNOME, I'll push it in Fedora Workstation. Either you provide a seamless upgrade path or we ship a way for it to work downstream. Breaking them is not an acceptable answer.

To make this clearer: because most applications use either libappindicator; Qt; or KNotifications to speak SNI, I would be satisfied if the new spec is supported in these implementations. That counts for "seamless upgrade path".

That's perfectly fine. Of course I want applications that uses these libraries to upgrade seamlessly. No problem.

The point of refusing to provide backwards-compat for the old protocol is to ensure that there is no behavior difference for sandboxed vs. unsandboxed applications. If your unsandboxed application shows a status notifier, it should not lose that status notifier when it is sandboxed, and there should be no reason to encourage an application developer to create a sandbox hole to make it work. This is a very important requirement. So apps that use old versions of these libraries, or apps that manually create the status notifier, really must break. But there should (probably) be no reason to force apps to port to new libraries.

My expectation is that there should be a binary shim for libappindicator consumers, because virtually all major users of that library are proprietary applications. So ABI for libappindicator will need to be preserved somehow.

Metadata Update from @aday:
- Issue set to the milestone: None (was: Fedora 38)

a year ago

To clarify: the action that is pending in this ticket is for someone to implement the new protocol.

Another possible approach could be developing some kind of proxy that would redirect apps that use SNI/systray to xdg-desktop-portal background portal or at least implementing some basic stub API functions of SNI/systray. That way, apps like Telegram (at least the Flatpaked one) would be able to run on background without having to use the buggy gnome-shell AppIndicator extension.

edit: Ignore what I said about Telegram. Telegram is now able to run on background on stock GNOME (without the AppIndicator extension) since latest update. There are no workarounds needed anymore.

The working group discussed this issue on September 20. The agreement back then was to organise an in-person or virtual hackfest with representatives from the main stakeholders, in order to move the new protocol forward.

@tpopela is investigating some of the logistics and we will discuss again in the next couple of weeks.

This issue is confusingly similar to #246. I understand this ticket is a subtask of #246, but I don't think it's helpful to have both open. It's a shame we have so much discussion split between the two different places, but I'm going to go ahead and close this one. Let's continue to discuss in #246.

Metadata Update from @catanzaro:
- Issue close_status updated to: Deferred to upstream
- Issue status updated to: Closed (was: Open)

11 months ago

Log in to comment on this ticket.

Metadata