dorkbox / SystemTray

Cross-platform SystemTray support for Swing/AWT, macOS, GtkStatusIcon, and AppIndicator on Java 8+
Other
427 stars 58 forks source link
appindicator awt cross-platform desktop desktop-environment gnome gtk gtk3 java jna linux mac-osx swing swt systemtray tray-icon tray-menu ubuntu

SystemTray

Git Github Gitlab

Professional, cross-platform SystemTray support for Swing/AWT, GtkStatusIcon, and AppIndicator on Java 8+.

This library provides OS Native menus and Swing/AWT menus, depending on the OS and Desktop Environment and if AutoDetect (the default) is enabled.

 

The following unique problems are also solved by this library:

  1. Sun/Oracle system-tray icons on Linux/Unix do not support images with transparent backgrounds
  2. Sun/Oracle system-tray and SWT system-tray implementations do not support app-indicators, which are necessary on different distributions of Linux/Unix
  3. GNOME3 desktop environments hide or remove entirely system tray icons (hidden from 3.16-3.25, removed from 3.26+)
  4. Sun/Oracle system-tray menus on Windows look absolutely horrid
  5. Sun/Oracle system-tray icons on Windows are hard-coded to a max size of 24x24 (it was last updated in 2006)
  6. Sun/Oracle AWT system-tray menus on MacOS do not respond to both mouse buttons, where native menus do
  7. Sun/Oracle AWT system-tray menus on MacOS do not support images, where native menus do
  8. Windows native menus do not support images attached to menu entries
  9. Windows menus do not support a different L&F from the running application
  10. Windows L&F is, by default, not the native L&F.
  11. java.awt.Desktop.getDesktop() is broken when using GTK3 or on MacOS.
  12. Windows, Linux, and MacOSX menus (native or otherwise) do not support HiDPI configurations
    1. Java8 is not DPI aware (so the icons + fonts must be scaled appropriately)
    2. Java 11+ is DPI aware, but must be explicitly enabled via native API calls
  13. Gnome/KDE environments no longer show system-tray icons without special shell extensions installed (this library will install and update them automatically)

This is for cross-platform use, specifically - linux 32/64/arm, mac 32/64/arm, and windows 32/64/arm. Java 8+

 
 

Linux

MacOS

Windows

   

Problems and Restrictions

AutoDetect Compatibility List

OS Supported
Arch Linux + Gnome3
Manjaro Linux + KDE
ChromeOS x
Debian 8.5 + Gnome3
Debian 8.6 + Gnome3
Debian 9.5 + Gnome3
Debian 9.5 + KDE
Debian 9.5 + Cinnamon
Debian 9.5 + MATE
Debian 9.5 + LXDE
Debian 9.5 + XFCE
Elementary OS 0.3.2
Elementary OS 0.4
Elementary OS 5.0 *
Fedora 23
Fedora 24
Fedora 25
Fedora 25 KDE
Fedora 26
Fedora 27
Fedora 28
Fedora 29
Fedora 39
FreeBSD 11 + Gnome3
IGEL OS 9.5
Kali 2016
Kali 2017
LinuxMint 18
LinuxMint 19
LinuxMint 20
Ubuntu 12.04
Ubuntu 14.04
Ubuntu 16.04
Ubuntu 17.04
Ubuntu 17.10
Ubuntu 18.04
Ubuntu 20.04
Ubuntu 22.04
UbuntuGnome 16.04
UbuntuGnome 17.04
Kubuntu 23.10
XUbuntu 16.04
MacOSx 10.x
MacOSx 11.x
MacOSx 12.x
MacOSx 13.x
MacOSx 14.x
Windows XP
Windows 7
Windows 8.1
Windows 10
Windows 11
WSL 1 x
WSL 2 x

Notes:

 
 

Customization parameters:

SystemTray.AUTO_SIZE   (type boolean, default value 'true')
 - Enables auto-detection for the system tray. This should be mostly successful.

SystemTray.APP_NAME   (type String, default value 'SystemTray')
 - Default name of the application, sometimes shows on tray-icon mouse over. Not used for all OSes, but mostly for Linux

SystemTray.FORCE_GTK2    (type boolean, default value 'false')
 - Forces the system tray to always choose GTK2 (even when GTK3 might be available).

SystemTray.PREFER_GTK3    (type boolean, default value 'true') 
 - Prefer to load GTK3 before trying to load GTK2.

SystemTray.FORCE_TRAY_TYPE   (type SystemTray.TrayType, default value 'AutoDetect')
 - Forces the system tray detection to be AutoDetect, GtkStatusIcon, AppIndicator, WindowsNotifyIcon, Swing, or AWT.
   This is an advanced feature, and it is recommended to leave it at AutoDetect.

SystemTray.AUTO_FIX_INCONSISTENCIES    (type boolean, default value 'true')
 -  Allows the SystemTray logic to resolve various OS inconsistencies for the SystemTray in different combinations

SystemTray.ENABLE_ROOT_CHECK    (type boolean, default value 'true')
 -  Allows the SystemTray logic to ignore if root is detected. Usually when running as root it will not work (because of 
    how DBUS operates), but in rare situations, it might work.
    This is an advanced feature, and it is recommended to leave as true 

SystemTray.SWING_UI    (type SwingUIFactory, default value 'null')
 - Allows the developer to provide a custom look and feel for the Swing UI, if defined. See the test example for specific use.

SystemTray.DEBUG    (type boolean, default value 'false')
 -  This property is provided for debugging any errors in the logic used to determine the system-tray type and initialization feedback.

SizeAndScalingLinux.OVERRIDE_MENU_SIZE    (type int, default value '0')
 - Allows overriding of the LINUX system tray MENU size (this is what shows in the system tray).

SizeAndScalingLinux.OVERRIDE_TRAY_SIZE    (type int, default value '0')
 - Allows overriding of the LINX system tray ICON size (this is what shows in the system tray).

SizeAndScalingMacOS.OVERRIDE_MENU_SIZE    (type int, default value '0')
 - Allows overriding of the MACOS system tray MENU size (this is what shows in the system tray).

SizeAndScalingMacOS.OVERRIDE_TRAY_SIZE    (type int, default value '0')
 - Allows overriding of the MACOS system tray ICON size (this is what shows in the system tray).

SizeAndScalingWindows.OVERRIDE_MENU_SIZE    (type int, default value '0')
 - Allows overriding of the WINDOWS system tray MENU size (this is what shows in the system tray).

SizeAndScalingWindows.OVERRIDE_TRAY_SIZE    (type int, default value '0')
 - Allows overriding of the WINDWOS system tray ICON size (this is what shows in the system tray).

GtkTheme.TRAY_IMAGE_SIZE_FALLBACK    (type int, default value '24')
 - Fallback for an unknown tray image size for GTK 

GtkTheme.TRAY_MENU_IMAGE_SIZE_FALLBACK    (type int, default value '16')
 - Fallback for an unknown tray menu image size for GTK

The test application is on Git, and a simple example is as follows:

    SystemTray.SWING_UI = new CustomSwingUI();

    SystemTray systemTray = SystemTray.get();
    if (systemTray == null) {
        throw new RuntimeException("Unable to load SystemTray!");
    }

    systemTray.setImage("grey_icon.png");
    systemTray.setStatus("Not Running");

    systemTray.getMenu().add(new MenuItem("Quit", new ActionListener() {
        @Override
        public
        void actionPerformed(final ActionEvent e) {
            systemTray.shutdown();
            //System.exit(0);  not necessary if all non-daemon threads have stopped.
        }
    })).setShortcut('q'); // case does not matter

 
 

Note: This project was heavily influenced by the excellent Lantern project (when it was Java based),
      *Many* thanks to them for figuring out AppIndicators via JNA.
      https://github.com/getlantern/lantern
Note: Gnome-shell users can install an extension to support placing the tray icon next to all 
      of other OS tray icons. By default, all tray icons go to a "Notification drawer" which 
      is initially hidden. 
Note: We have fixed the Swing notification tray on Linux (it no longer has a greyish background), however
      to facilitate this, a screen-shot is grabbed where the icon is. Because this must happen after the
      icon is placed, *sometimes* you can see this happen. Unfortunately this is the only way to fix
      this problem, and there are no other known workarounds outside of writing an X11 wrapper from scratch.

 
 

ISSUES:
      'Trying to remove a child that doesn't believe we're it's parent.'

      This is a known appindicator bug, and is rather old. Some distributions use 
      an OLD version of libappindicator, and will see this error. 
         See: https://github.com/ValveSoftware/steam-for-linux/issues/1077
      -----------------------   

      'gsignal.c: signal 'child-added' is invalid for instance 'xyz' of type 'GtkMenu''

      This is a known appindicator bug, and is rather old. Some distributions use an 
      OLD version of libappindicator, and will see this error. 

      The fallout from this issue (ie: menu entries not displaying) has been 
      *worked around*, so the menus should still show correctly.
         See: https://askubuntu.com/questions/364594/has-the-appindicator-or-gtkmenu-api-changed-in-saucy
      -----------------------   

      Gdk-WARNING XSetErrorHandler() called with a GDK error trap pushed. Don't do that.

      This is a bug specifically with JavaFX +GTK3. From what I can tell, this not something that can be fixed.
        (bugs)
        https://stackoverflow.com/questions/55446534/how-to-fix-java22494-gdk-warning
        https://bugs.openjdk.java.net/browse/JDK-8156779
        https://bugs.openjdk.java.net/browse/JDK-8211305

        (Source files)
        https://github.com/openjdk/jfx/blob/master/modules/javafx.graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java
        https://github.com/openjdk/jfx/blob/master/modules/javafx.graphics/src/main/native-glass/gtk/GlassApplication.cpp

        (Where the error occurs)
        https://gitlab.gnome.org/GNOME/gtk/-/blob/master/gdk/x11/gdkmain-x11.c

   

Maven Info

<dependencies>
    ...
    <dependency>
      <groupId>com.dorkbox</groupId>
      <artifactId>SystemTray</artifactId>
      <version>4.5</version>
    </dependency>
</dependencies>

Gradle Info

dependencies {
    ...
    implementation("com.dorkbox:SystemTray:4.5")
}

License

This project is © 2023 dorkbox llc, and is distributed under the terms of the Apache v2.0 License. See file "LICENSE" for further references.