Hello,

I'm Marco Matessi. This is my first OpenJDK contribution; I have
signed the OCA. I've
put together an implementation for JDK-8035556 and would like feedback
on the approach
before opening a formal RFR.

The problem: on Ubuntu 24 and modern Wayland/GNOME desktops the legacy
X11 XEmbed
system tray protocol is no longer supported, so java.awt.TrayIcon is
effectively broken
there (see also JDK-8341144, PR #23329, which skips the test on
Wayland). The de facto
standard on current Linux desktops is the StatusNotifierItem (SNI)
D-Bus protocol used
by KDE, GNOME Shell extensions and AppIndicator.

What I've done: a working SNI peer implemented over D-Bus. When
org.kde.StatusNotifierWatcher is present on the session bus, TrayIcon/SystemTray
delegate to the SNI peer; otherwise they fall back to the existing X11
XEmbed peer.
XToolkit.createTrayIcon/createSystemTray/isTraySupported dispatch on that basis.

The D-Bus layer uses Panama FFM (java.lang.foreign) against
libdbus-1.so.3, with no
new JNI code and no new native build artifacts. New classes live in sun.awt.X11:
SNIDBusLib (FFM bindings), SNIMsg (DBusMessage wrapper), SNIDBusConn (session
connection + dispatch loop), SNITrayIconPeer (org.kde.StatusNotifierItem +
com.canonical.dbusmenu) and SNISystemTrayPeer. The dispatch loop runs on its own
platform thread, independent of the GTK L&F.

Why FFM rather than GDBus/JNI:
- It follows the declared direction away from JNI toward Panama FFM; new C in
  libawt_xawt would go the other way.
- libdbus-1 is not deprecated. GDBus is a wrapper over it, not a replacement.
- SystemTray should not depend on the Look&Feel; a GDBus/GTK path
would force GTK
  init even for Metal/Nimbus apps.
- dbus_bus_get_private yields a separate connection, so there's no
GMainLoop conflict
  with any GTK-internal D-Bus usage.

The implementation has been built and tested on Ubuntu 24.04 (GNOME, with the
AppIndicator shell extension) and includes three jtreg regression tests
(SNITrayIconTest, SNITrayIconPropertiesTest, SNIFallbackTest).

Two open items I'd like input on: currently there is one private
connection and one
dispatch thread per peer; a singleton shared connection is cleaner and
I'll implement
it based on feedback. SNITrayIconPeer is ~850 lines and I plan to split out an
SNIDBusMenu class.

Code (fork, branch JDK-8035556): https://github.com/basix86/jdk

I'd appreciate any guidance on the overall approach.

Thanks,
Marco Matessi

Reply via email to