It's February 2020 and my
riot-desktop
tray icon
vanished.
Electron (Chrome, rather) dropped support for the
System Tray Protocol Specification:
an old but widely used system tray protocol for the Linux desktop.
Chrome moved to
StatusNotifierItem
(SNI),
a D-Bus based protocol that — while still too complicated for my tastes —
is simpler than the X based tray protocol, and ready for Wayland.
The problem: I was not ready for Wayland. I was running dwm with a tray bar
patch that doesn't support SNI. Convincing Electron to reconsider seemed
impossible, so I looked for another way.
The solution: implement the bare minimum of SNI and then "translate" it to
the old protocol. Thus
snixembed
was born.
I do not understand Xorg, and I did not feel like learning legacy technology
(for which there is surprisingly little tutorial-style documentation online).
So I decided to use a toolkit to handle the translation: I would set up the
proper D-Bus services, parse the data, and leave the rest to Qt.
It didn't work: QSystemTrayIcon does not allow for choosing the backend. As
soon as I started impersonating an SNI host properly, Qt started talking SNI
back to me instead of XEmbed to my old tray.
Then I tried GTK. It worked: GTK didn't (and probably still doesn't) support
the new tray icon specifications, because they had stopped believing in system
trays since GNOME 3. The old implementation was marked deprecated as well. That
didn't bother me much: I had little free time and wanted my icons back, fast.
I decided to use
Vala,
a language I used previously for a never published project. Vala has a simple
(too simple, it turned out) abstraction over D-Bus and is made specifically for
using GTK. That meant writing less code. Less code is my first ingredient for
finished projects.
Two days later, snixembed worked. The code was awful, slapped together in a few
hours with little design considerations. But I had my icons back, so I was
happy. I put it on sourcehut (warning for crappy code and incomplete
functionality), and announced it on the Arch Linux forums.
I didn't expect anyone to use it, but someone did. I saw people recommending
snixembed on GitHub. I got sourcehut tickets, and made a Matrix room that saw
use. Small numbers, about ten people in total. Far more interaction than I had
expected.
I no longer use snixembed. Months after its creation, Electron decided to
reintroduce its legacy tray code. Some time later it had hit production. I
spread the word, and expected that would be the happy end of snixembed.
But once in a while, someone comes around with a bug or feature request. These
people do not use snixembed in any way I would have imagined. One person uses
(used?) it because they were running a KDE session but without its tray, and
just the KDE session being there made applications ignore their legacy tray.
Someone is using obscure apps that only use AppIndicator. (AI was Canonicals
"competitor" to SNI that uses the same service names as SNI but then breaks
from it in silly ways. I could write a whole blog post about the pains of this
and other ways in which the ecosystem manages to just diverge from quite simple
specifications and how I worked around it.) It's fun to see my project live
longer than I have a need for it to.
These are the things I learned from snixembed:
- Sometimes writing ugly code is the best way to finish a project.
- Publish early. People will find your project, use your project. Some will
report bugs, help fixing bugs. It's useful and motivating.
- People will use your software in unexpected ways.
- It's nice to fix bugs and it's important to do so only when it's convenient.
- When implementing a protocol, do so faithfully — expect others do not.
- Dirty hacks can make a difference.