diff --git a/src/dorkbox/systemTray/jna/linux/AppIndicator.java b/src/dorkbox/systemTray/jna/linux/AppIndicator.java index b7d72a3..ab43558 100644 --- a/src/dorkbox/systemTray/jna/linux/AppIndicator.java +++ b/src/dorkbox/systemTray/jna/linux/AppIndicator.java @@ -23,6 +23,7 @@ import com.sun.jna.Pointer; import dorkbox.systemTray.SystemTray; import dorkbox.systemTray.jna.JnaHelper; +import dorkbox.util.OS; /** * bindings for libappindicator @@ -32,8 +33,8 @@ import dorkbox.systemTray.jna.JnaHelper; @SuppressWarnings({"Duplicates", "SameParameterValue", "DanglingJavadoc"}) public class AppIndicator { - public static boolean isVersion3 = false; - public static boolean isLoaded = false; + public static final boolean isVersion3; + public static final boolean isLoaded; /** * Loader for AppIndicator, because it is absolutely mindboggling how those whom maintain the standard, can't agree to what that @@ -44,6 +45,13 @@ class AppIndicator { * This is so hacky it makes me sick. */ static { + boolean _isVersion3 = false; + boolean _isLoaded = false; + + if (!OS.isLinux()) { + _isLoaded = true; + } + // objdump -T /usr/lib/x86_64-linux-gnu/libappindicator.so.1 | grep foo // objdump -T /usr/lib/x86_64-linux-gnu/libappindicator3.so.1 | grep foo @@ -52,22 +60,22 @@ class AppIndicator { // appindiactor1 is GKT2 only (can't use GTK3 bindings with it) // appindicator3 doesn't support menu icons via GTK2!! - if (SystemTray.FORCE_TRAY_TYPE == SystemTray.TrayType.GtkStatusIcon) { + if (!_isLoaded && SystemTray.FORCE_TRAY_TYPE == SystemTray.TrayType.GtkStatusIcon) { // if we force GTK type system tray, don't attempt to load AppIndicator libs if (SystemTray.DEBUG) { logger.debug("Forcing GTK tray, not using appindicator"); } - isLoaded = true; + _isLoaded = true; } - if (!isLoaded && SystemTray.FORCE_GTK2) { + if (!_isLoaded && SystemTray.FORCE_GTK2) { // if specified, try loading appindicator1 first, maybe it's there? // note: we can have GTK2 + appindicator3, but NOT ALWAYS. try { // deliberately without the "1" at the end. final NativeLibrary library = JnaHelper.register("appindicator", AppIndicator.class); if (library != null) { - isLoaded = true; + _isLoaded = true; } } catch (Throwable e) { if (SystemTray.DEBUG) { @@ -87,7 +95,7 @@ class AppIndicator { } // start with base version using whatever the OS specifies as the proper symbolic link - if (!isLoaded) { + if (!_isLoaded) { try { final NativeLibrary library = JnaHelper.register(nameToCheck1, AppIndicator.class); String s = library.getFile().getName(); @@ -97,10 +105,10 @@ class AppIndicator { } if (s.contains("appindicator3")) { - isVersion3 = true; + _isVersion3 = true; } - isLoaded = true; + _isLoaded = true; } catch (Throwable e) { if (SystemTray.DEBUG) { logger.debug("Error loading library: '{}'. \n{}", nameToCheck1, e.getMessage()); @@ -110,7 +118,7 @@ class AppIndicator { // whoops. Symbolic links are bugged out. Look manually for it... // Super hacky way to do this. - if (!isLoaded) { + if (!_isLoaded) { if (Gtk.isGtk2) { if (SystemTray.DEBUG) { logger.debug("Checking GTK2 first for appIndicator"); @@ -118,7 +126,7 @@ class AppIndicator { // have to check gtk2 first for (int i = 0; i <= 10; i++) { - if (!isLoaded) { + if (!_isLoaded) { try { final NativeLibrary library = JnaHelper.register("appindicator" + i, AppIndicator.class); String s = library.getFile().getName(); @@ -129,14 +137,14 @@ class AppIndicator { // version 3 WILL NOT work with icons in the menu. This allows us to show a warning (in the System tray initialization) if (i == 3 || s.contains("appindicator3")) { - isVersion3 = true; + _isVersion3 = true; if (SystemTray.DEBUG) { logger.debug("Unloading library: '{}'", s); } Native.unregister(AppIndicator.class); } - isLoaded = true; + _isLoaded = true; break; } catch (Throwable e) { if (SystemTray.DEBUG) { @@ -149,7 +157,7 @@ class AppIndicator { } else { // have to check gtk3 first (maybe it's there?) for (int i = 10; i >= 0; i--) { - if (!isLoaded) { + if (!_isLoaded) { try { final NativeLibrary library = JnaHelper.register("appindicator" + i, AppIndicator.class); String s = library.getFile().getName(); @@ -160,10 +168,10 @@ class AppIndicator { // version 3 WILL NOT work with icons in the menu. This allows us to show a warning (in the System tray initialization) if (i == 3 || s.contains("appindicator3")) { - isVersion3 = true; + _isVersion3 = true; } - isLoaded = true; + _isLoaded = true; break; } catch (Throwable e) { if (SystemTray.DEBUG) { @@ -176,10 +184,10 @@ class AppIndicator { } // maybe it's really GTK2 version? who knows... - if (!isLoaded) { + if (!_isLoaded) { try { JnaHelper.register("appindicator", AppIndicator.class); - isLoaded = true; + _isLoaded = true; } catch (Throwable e) { if (SystemTray.DEBUG) { logger.debug("Error loading library: '{}'. \n{}", "appindicator", e.getMessage()); @@ -199,10 +207,10 @@ class AppIndicator { } // another type. who knows... - if (!isLoaded) { + if (!_isLoaded) { try { JnaHelper.register(nameToCheck1, AppIndicator.class); - isLoaded = true; + _isLoaded = true; } catch (Throwable e) { if (SystemTray.DEBUG) { logger.debug("Error loading library: '{}'. \n{}", nameToCheck1, e.getMessage()); @@ -211,16 +219,24 @@ class AppIndicator { } // this is HORRID. such a PITA - if (!isLoaded) { + if (!_isLoaded) { try { JnaHelper.register(nameToCheck2, AppIndicator.class); - isLoaded = true; + _isLoaded = true; } catch (Throwable e) { if (SystemTray.DEBUG) { logger.debug("Error loading library: '{}'. \n{}", nameToCheck2, e.getMessage()); } } } + + if (OS.isLinux()) { + isLoaded = _isLoaded; + isVersion3 = _isVersion3; + } else { + isLoaded = false; + isVersion3 = false; + } } // Note: AppIndicators DO NOT support tooltips, as per mark shuttleworth. Rather stupid IMHO. diff --git a/src/dorkbox/systemTray/jna/linux/Gtk.java b/src/dorkbox/systemTray/jna/linux/Gtk.java index 92ebcb5..c9c55d4 100644 --- a/src/dorkbox/systemTray/jna/linux/Gtk.java +++ b/src/dorkbox/systemTray/jna/linux/Gtk.java @@ -31,6 +31,7 @@ import dorkbox.systemTray.SystemTray; import dorkbox.systemTray.jna.JnaHelper; import dorkbox.systemTray.util.JavaFX; import dorkbox.systemTray.util.Swt; +import dorkbox.util.OS; /** * bindings for gtk 2 or 3 @@ -48,13 +49,13 @@ class Gtk { // https://github.com/syncthing/syncthing-gtk/blob/b7a3bc00e3bb6d62365ae62b5395370f3dcc7f55/syncthing_gtk/statusicon.py // NOTE: AppIndicator uses this info to figure out WHAT VERSION OF appindicator to use: GTK2 -> appindicator1, GTK3 -> appindicator3 - public static volatile boolean isGtk2 = false; - public static boolean isLoaded = false; - + public static final boolean isGtk2; + public static final boolean isGtk3; + public static final boolean isLoaded; public static Function gtk_status_icon_position_menu = null; - private static boolean alreadyRunningGTK = false; + private static final boolean alreadyRunningGTK; // This is required because the EDT needs to have it's own value for this boolean, that is a different value than the main thread private static ThreadLocal isDispatch = new ThreadLocal() { @@ -79,26 +80,37 @@ class Gtk { */ static { boolean shouldUseGtk2 = SystemTray.FORCE_GTK2; + boolean _isGtk2 = false; + boolean _isLoaded = false; + boolean _alreadyRunningGTK = false; + + if (!OS.isLinux()) { + _isLoaded = true; + } + + // we can force the system to use the swing indicator, which WORKS, but doesn't support transparency in the icon. + if (!_isLoaded && SystemTray.FORCE_TRAY_TYPE == SystemTray.TrayType.Swing) { + if (SystemTray.DEBUG) { + logger.debug("Forcing Swing tray, not using GTK"); + } + _isLoaded = true; + } // in some cases, we ALWAYS want to try GTK2 first String gtk2LibName = "gtk-x11-2.0"; String gtk3LibName = "libgtk-3.so.0"; - // we can force the system to use the swing indicator, which WORKS, but doesn't support transparency in the icon. - if (SystemTray.FORCE_TRAY_TYPE == SystemTray.TrayType.Swing) { - isLoaded = true; - } - if (!isLoaded && shouldUseGtk2) { + if (!_isLoaded && shouldUseGtk2) { try { JnaHelper.register(gtk2LibName, Gtk.class); gtk_status_icon_position_menu = Function.getFunction(gtk2LibName, "gtk_status_icon_position_menu"); - isGtk2 = true; + _isGtk2 = true; // when running inside of JavaFX, this will be '1'. All other times this should be '0' // when it's '1', it means that someone else has started GTK -- so we DO NOT NEED TO. - alreadyRunningGTK = gtk_main_level() != 0; - isLoaded = true; + _alreadyRunningGTK = gtk_main_level() != 0; + _isLoaded = true; if (SystemTray.DEBUG) { logger.debug("GTK: {}", gtk2LibName); @@ -113,14 +125,14 @@ class Gtk { // now for the defaults... // start with version 3 - if (!isLoaded) { + if (!_isLoaded) { try { JnaHelper.register(gtk3LibName, Gtk.class); gtk_status_icon_position_menu = Function.getFunction(gtk3LibName, "gtk_status_icon_position_menu"); // when running inside of JavaFX, this will be '1'. All other times this should be '0' // when it's '1', it means that someone else has started GTK -- so we DO NOT NEED TO. - alreadyRunningGTK = gtk_main_level() != 0; - isLoaded = true; + _alreadyRunningGTK = gtk_main_level() != 0; + _isLoaded = true; if (SystemTray.DEBUG) { logger.debug("GTK: {}", gtk3LibName); @@ -133,16 +145,16 @@ class Gtk { } // now version 2 - if (!isLoaded) { + if (!_isLoaded) { try { JnaHelper.register(gtk2LibName, Gtk.class); gtk_status_icon_position_menu = Function.getFunction(gtk2LibName, "gtk_status_icon_position_menu"); - isGtk2 = true; + _isGtk2 = true; // when running inside of JavaFX, this will be '1'. All other times this should be '0' // when it's '1', it means that someone else has started GTK -- so we DO NOT NEED TO. - alreadyRunningGTK = gtk_main_level() != 0; - isLoaded = true; + _alreadyRunningGTK = gtk_main_level() != 0; + _isLoaded = true; if (SystemTray.DEBUG) { logger.debug("GTK: {}", gtk2LibName); @@ -154,15 +166,27 @@ class Gtk { } } - // depending on how the system is initialized, SWT may, or may not, have the gtk_main loop running. It will EVENTUALLY run, so we - // do not want to run our own GTK event loop. - alreadyRunningGTK |= SystemTray.isSwtLoaded; + isLoaded = _isLoaded; - if (SystemTray.DEBUG) { - logger.debug("Is the system already running GTK? {}", alreadyRunningGTK); + if (_isLoaded) { + // depending on how the system is initialized, SWT may, or may not, have the gtk_main loop running. It will EVENTUALLY run, so we + // do not want to run our own GTK event loop. + _alreadyRunningGTK |= SystemTray.isSwtLoaded; + + if (SystemTray.DEBUG) { + logger.debug("Is the system already running GTK? {}", _alreadyRunningGTK); + } + + alreadyRunningGTK = _alreadyRunningGTK; + isGtk2 = _isGtk2; + isGtk3 = !_isGtk2; + } else { + alreadyRunningGTK = false; + isGtk2 = false; + isGtk3 = false; } - if (!isLoaded) { + if (OS.isLinux() && !_isLoaded) { throw new RuntimeException("We apologize for this, but we are unable to determine the GTK library is in use, " + "or even if it is in use... Please create an issue for this and include your OS type and configuration."); }