Added isGtk3, changed static fields to be final.

This commit is contained in:
nathan 2016-12-28 21:41:49 +01:00
parent e3fbec2c55
commit 8dfd2d3317
2 changed files with 87 additions and 47 deletions

View File

@ -23,6 +23,7 @@ import com.sun.jna.Pointer;
import dorkbox.systemTray.SystemTray; import dorkbox.systemTray.SystemTray;
import dorkbox.systemTray.jna.JnaHelper; import dorkbox.systemTray.jna.JnaHelper;
import dorkbox.util.OS;
/** /**
* bindings for libappindicator * bindings for libappindicator
@ -32,8 +33,8 @@ import dorkbox.systemTray.jna.JnaHelper;
@SuppressWarnings({"Duplicates", "SameParameterValue", "DanglingJavadoc"}) @SuppressWarnings({"Duplicates", "SameParameterValue", "DanglingJavadoc"})
public public
class AppIndicator { class AppIndicator {
public static boolean isVersion3 = false; public static final boolean isVersion3;
public static boolean isLoaded = false; 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 * 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. * This is so hacky it makes me sick.
*/ */
static { 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/libappindicator.so.1 | grep foo
// objdump -T /usr/lib/x86_64-linux-gnu/libappindicator3.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) // appindiactor1 is GKT2 only (can't use GTK3 bindings with it)
// appindicator3 doesn't support menu icons via GTK2!! // 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 we force GTK type system tray, don't attempt to load AppIndicator libs
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("Forcing GTK tray, not using appindicator"); 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? // if specified, try loading appindicator1 first, maybe it's there?
// note: we can have GTK2 + appindicator3, but NOT ALWAYS. // note: we can have GTK2 + appindicator3, but NOT ALWAYS.
try { try {
// deliberately without the "1" at the end. // deliberately without the "1" at the end.
final NativeLibrary library = JnaHelper.register("appindicator", AppIndicator.class); final NativeLibrary library = JnaHelper.register("appindicator", AppIndicator.class);
if (library != null) { if (library != null) {
isLoaded = true; _isLoaded = true;
} }
} catch (Throwable e) { } catch (Throwable e) {
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
@ -87,7 +95,7 @@ class AppIndicator {
} }
// start with base version using whatever the OS specifies as the proper symbolic link // start with base version using whatever the OS specifies as the proper symbolic link
if (!isLoaded) { if (!_isLoaded) {
try { try {
final NativeLibrary library = JnaHelper.register(nameToCheck1, AppIndicator.class); final NativeLibrary library = JnaHelper.register(nameToCheck1, AppIndicator.class);
String s = library.getFile().getName(); String s = library.getFile().getName();
@ -97,10 +105,10 @@ class AppIndicator {
} }
if (s.contains("appindicator3")) { if (s.contains("appindicator3")) {
isVersion3 = true; _isVersion3 = true;
} }
isLoaded = true; _isLoaded = true;
} catch (Throwable e) { } catch (Throwable e) {
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("Error loading library: '{}'. \n{}", nameToCheck1, e.getMessage()); 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... // whoops. Symbolic links are bugged out. Look manually for it...
// Super hacky way to do this. // Super hacky way to do this.
if (!isLoaded) { if (!_isLoaded) {
if (Gtk.isGtk2) { if (Gtk.isGtk2) {
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("Checking GTK2 first for appIndicator"); logger.debug("Checking GTK2 first for appIndicator");
@ -118,7 +126,7 @@ class AppIndicator {
// have to check gtk2 first // have to check gtk2 first
for (int i = 0; i <= 10; i++) { for (int i = 0; i <= 10; i++) {
if (!isLoaded) { if (!_isLoaded) {
try { try {
final NativeLibrary library = JnaHelper.register("appindicator" + i, AppIndicator.class); final NativeLibrary library = JnaHelper.register("appindicator" + i, AppIndicator.class);
String s = library.getFile().getName(); 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) // 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")) { if (i == 3 || s.contains("appindicator3")) {
isVersion3 = true; _isVersion3 = true;
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("Unloading library: '{}'", s); logger.debug("Unloading library: '{}'", s);
} }
Native.unregister(AppIndicator.class); Native.unregister(AppIndicator.class);
} }
isLoaded = true; _isLoaded = true;
break; break;
} catch (Throwable e) { } catch (Throwable e) {
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
@ -149,7 +157,7 @@ class AppIndicator {
} else { } else {
// have to check gtk3 first (maybe it's there?) // have to check gtk3 first (maybe it's there?)
for (int i = 10; i >= 0; i--) { for (int i = 10; i >= 0; i--) {
if (!isLoaded) { if (!_isLoaded) {
try { try {
final NativeLibrary library = JnaHelper.register("appindicator" + i, AppIndicator.class); final NativeLibrary library = JnaHelper.register("appindicator" + i, AppIndicator.class);
String s = library.getFile().getName(); 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) // 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")) { if (i == 3 || s.contains("appindicator3")) {
isVersion3 = true; _isVersion3 = true;
} }
isLoaded = true; _isLoaded = true;
break; break;
} catch (Throwable e) { } catch (Throwable e) {
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
@ -176,10 +184,10 @@ class AppIndicator {
} }
// maybe it's really GTK2 version? who knows... // maybe it's really GTK2 version? who knows...
if (!isLoaded) { if (!_isLoaded) {
try { try {
JnaHelper.register("appindicator", AppIndicator.class); JnaHelper.register("appindicator", AppIndicator.class);
isLoaded = true; _isLoaded = true;
} catch (Throwable e) { } catch (Throwable e) {
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("Error loading library: '{}'. \n{}", "appindicator", e.getMessage()); logger.debug("Error loading library: '{}'. \n{}", "appindicator", e.getMessage());
@ -199,10 +207,10 @@ class AppIndicator {
} }
// another type. who knows... // another type. who knows...
if (!isLoaded) { if (!_isLoaded) {
try { try {
JnaHelper.register(nameToCheck1, AppIndicator.class); JnaHelper.register(nameToCheck1, AppIndicator.class);
isLoaded = true; _isLoaded = true;
} catch (Throwable e) { } catch (Throwable e) {
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("Error loading library: '{}'. \n{}", nameToCheck1, e.getMessage()); logger.debug("Error loading library: '{}'. \n{}", nameToCheck1, e.getMessage());
@ -211,16 +219,24 @@ class AppIndicator {
} }
// this is HORRID. such a PITA // this is HORRID. such a PITA
if (!isLoaded) { if (!_isLoaded) {
try { try {
JnaHelper.register(nameToCheck2, AppIndicator.class); JnaHelper.register(nameToCheck2, AppIndicator.class);
isLoaded = true; _isLoaded = true;
} catch (Throwable e) { } catch (Throwable e) {
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("Error loading library: '{}'. \n{}", nameToCheck2, e.getMessage()); 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. // Note: AppIndicators DO NOT support tooltips, as per mark shuttleworth. Rather stupid IMHO.

View File

@ -31,6 +31,7 @@ import dorkbox.systemTray.SystemTray;
import dorkbox.systemTray.jna.JnaHelper; import dorkbox.systemTray.jna.JnaHelper;
import dorkbox.systemTray.util.JavaFX; import dorkbox.systemTray.util.JavaFX;
import dorkbox.systemTray.util.Swt; import dorkbox.systemTray.util.Swt;
import dorkbox.util.OS;
/** /**
* bindings for gtk 2 or 3 * bindings for gtk 2 or 3
@ -48,13 +49,13 @@ class Gtk {
// https://github.com/syncthing/syncthing-gtk/blob/b7a3bc00e3bb6d62365ae62b5395370f3dcc7f55/syncthing_gtk/statusicon.py // 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 // 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 final boolean isGtk2;
public static boolean isLoaded = false; public static final boolean isGtk3;
public static final boolean isLoaded;
public static Function gtk_status_icon_position_menu = null; 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 // 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<Boolean> isDispatch = new ThreadLocal<Boolean>() { private static ThreadLocal<Boolean> isDispatch = new ThreadLocal<Boolean>() {
@ -79,26 +80,37 @@ class Gtk {
*/ */
static { static {
boolean shouldUseGtk2 = SystemTray.FORCE_GTK2; 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 // in some cases, we ALWAYS want to try GTK2 first
String gtk2LibName = "gtk-x11-2.0"; String gtk2LibName = "gtk-x11-2.0";
String gtk3LibName = "libgtk-3.so.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 { try {
JnaHelper.register(gtk2LibName, Gtk.class); JnaHelper.register(gtk2LibName, Gtk.class);
gtk_status_icon_position_menu = Function.getFunction(gtk2LibName, "gtk_status_icon_position_menu"); 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 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. // when it's '1', it means that someone else has started GTK -- so we DO NOT NEED TO.
alreadyRunningGTK = gtk_main_level() != 0; _alreadyRunningGTK = gtk_main_level() != 0;
isLoaded = true; _isLoaded = true;
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("GTK: {}", gtk2LibName); logger.debug("GTK: {}", gtk2LibName);
@ -113,14 +125,14 @@ class Gtk {
// now for the defaults... // now for the defaults...
// start with version 3 // start with version 3
if (!isLoaded) { if (!_isLoaded) {
try { try {
JnaHelper.register(gtk3LibName, Gtk.class); JnaHelper.register(gtk3LibName, Gtk.class);
gtk_status_icon_position_menu = Function.getFunction(gtk3LibName, "gtk_status_icon_position_menu"); 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 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. // when it's '1', it means that someone else has started GTK -- so we DO NOT NEED TO.
alreadyRunningGTK = gtk_main_level() != 0; _alreadyRunningGTK = gtk_main_level() != 0;
isLoaded = true; _isLoaded = true;
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("GTK: {}", gtk3LibName); logger.debug("GTK: {}", gtk3LibName);
@ -133,16 +145,16 @@ class Gtk {
} }
// now version 2 // now version 2
if (!isLoaded) { if (!_isLoaded) {
try { try {
JnaHelper.register(gtk2LibName, Gtk.class); JnaHelper.register(gtk2LibName, Gtk.class);
gtk_status_icon_position_menu = Function.getFunction(gtk2LibName, "gtk_status_icon_position_menu"); 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 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. // when it's '1', it means that someone else has started GTK -- so we DO NOT NEED TO.
alreadyRunningGTK = gtk_main_level() != 0; _alreadyRunningGTK = gtk_main_level() != 0;
isLoaded = true; _isLoaded = true;
if (SystemTray.DEBUG) { if (SystemTray.DEBUG) {
logger.debug("GTK: {}", gtk2LibName); 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 isLoaded = _isLoaded;
// do not want to run our own GTK event loop.
alreadyRunningGTK |= SystemTray.isSwtLoaded;
if (SystemTray.DEBUG) { if (_isLoaded) {
logger.debug("Is the system already running GTK? {}", alreadyRunningGTK); // 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, " + 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."); "or even if it is in use... Please create an issue for this and include your OS type and configuration.");
} }