forked from dorkbox/SystemTray
Refactored out JavaFX (similar to how SWT was done) so that we can
compile to Java 1.6
This commit is contained in:
parent
efeda2fac3
commit
3d8459ecc3
@ -23,7 +23,6 @@ import java.io.File;
|
|||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -41,6 +40,8 @@ import dorkbox.systemTray.linux.GtkSystemTray;
|
|||||||
import dorkbox.systemTray.linux.jna.AppIndicator;
|
import dorkbox.systemTray.linux.jna.AppIndicator;
|
||||||
import dorkbox.systemTray.linux.jna.Gtk;
|
import dorkbox.systemTray.linux.jna.Gtk;
|
||||||
import dorkbox.systemTray.swing.SwingSystemTray;
|
import dorkbox.systemTray.swing.SwingSystemTray;
|
||||||
|
import dorkbox.systemTray.util.JavaFX;
|
||||||
|
import dorkbox.systemTray.util.Swt;
|
||||||
import dorkbox.util.OS;
|
import dorkbox.util.OS;
|
||||||
import dorkbox.util.Property;
|
import dorkbox.util.Property;
|
||||||
import dorkbox.util.process.ShellProcessBuilder;
|
import dorkbox.util.process.ShellProcessBuilder;
|
||||||
@ -85,7 +86,7 @@ class SystemTray {
|
|||||||
/**
|
/**
|
||||||
* This property is provided for debugging any errors in the logic used to determine the system-tray type.
|
* This property is provided for debugging any errors in the logic used to determine the system-tray type.
|
||||||
*/
|
*/
|
||||||
public static boolean DEBUG = false;
|
public static boolean DEBUG = true;
|
||||||
|
|
||||||
|
|
||||||
private static volatile SystemTray systemTray = null;
|
private static volatile SystemTray systemTray = null;
|
||||||
@ -95,21 +96,15 @@ class SystemTray {
|
|||||||
public final static boolean isSwtLoaded;
|
public final static boolean isSwtLoaded;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// maybe we should load the SWT version? (In order for us to work with SWT, BOTH must be GTK2!!
|
|
||||||
// SWT is GTK2, but if -DSWT_GTK3=1 is specified, it can be GTK3
|
|
||||||
// JavaFX Java7,8 is GTK2 only. Java9 can have it be GTK3 if -Djdk.gtk.version=3 is specified
|
|
||||||
// see http://mail.openjdk.java.net/pipermail/openjfx-dev/2016-May/019100.html
|
|
||||||
|
|
||||||
boolean isJavaFxLoaded_ = false;
|
boolean isJavaFxLoaded_ = false;
|
||||||
boolean isSwtLoaded_ = false;
|
boolean isSwtLoaded_ = false;
|
||||||
try {
|
try {
|
||||||
// First check if JavaFX is loaded - if it's NOT LOADED, then we only proceed if COMPATIBILITY_MODE is enabled.
|
// JavaFX Java7,8 is GTK2 only. Java9 can have it be GTK3 if -Djdk.gtk.version=3 is specified
|
||||||
// this is important, because if JavaFX is not being used, calling getToolkit() will initialize it...
|
// see http://mail.openjdk.java.net/pipermail/openjfx-dev/2016-May/019100.html
|
||||||
java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
|
isJavaFxLoaded_ = JavaFX.isLoaded();
|
||||||
m.setAccessible(true);
|
|
||||||
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
// SWT is GTK2, but if -DSWT_GTK3=1 is specified, it can be GTK3
|
||||||
isJavaFxLoaded_ = (null != m.invoke(cl, "com.sun.javafx.tk.Toolkit")) || (null != m.invoke(cl, "javafx.application.Application"));
|
isSwtLoaded_ = Swt.isLoaded();
|
||||||
isSwtLoaded_ = null != m.invoke(cl, "org.eclipse.swt.widgets.Display");
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
logger.debug("Error detecting javaFX/SWT mode", e);
|
logger.debug("Error detecting javaFX/SWT mode", e);
|
||||||
@ -547,65 +542,28 @@ class SystemTray {
|
|||||||
if (isJavaFxLoaded) {
|
if (isJavaFxLoaded) {
|
||||||
// Necessary because javaFX **ALSO** runs a gtk main loop, and when it stops (if we don't stop first), we become unresponsive.
|
// Necessary because javaFX **ALSO** runs a gtk main loop, and when it stops (if we don't stop first), we become unresponsive.
|
||||||
// Also, it's nice to have us shutdown at the same time as the main application
|
// Also, it's nice to have us shutdown at the same time as the main application
|
||||||
|
JavaFX.onShutdown(new Runnable() {
|
||||||
// com.sun.javafx.tk.Toolkit.getToolkit()
|
@Override
|
||||||
// .addShutdownHook(new Runnable() {
|
public
|
||||||
// @Override
|
void run() {
|
||||||
// public
|
if (systemTray != null) {
|
||||||
// void run() {
|
systemTray.shutdown();
|
||||||
// systemTray.shutdown();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName("com.sun.javafx.tk.Toolkit");
|
|
||||||
Method method = clazz.getMethod("getToolkit");
|
|
||||||
Object o = method.invoke(null);
|
|
||||||
Method runnable = o.getClass()
|
|
||||||
.getMethod("addShutdownHook", Runnable.class);
|
|
||||||
runnable.invoke(o, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public
|
|
||||||
void run() {
|
|
||||||
if (systemTray != null) {
|
|
||||||
systemTray.shutdown();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
} catch (Throwable e) {
|
|
||||||
if (DEBUG) {
|
|
||||||
logger.error("Cannot initialize JavaFX", e);
|
|
||||||
}
|
}
|
||||||
logger.error("Unable to insert shutdown hook into JavaFX. Please create an issue with your OS and Java " +
|
});
|
||||||
"version so we may further investigate this issue.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (isSwtLoaded) {
|
else if (isSwtLoaded) {
|
||||||
// this is because SWT **ALSO** runs a gtk main loop, and when it stops (if we don't stop first), we become unresponsive
|
// this is because SWT **ALSO** runs a gtk main loop, and when it stops (if we don't stop first), we become unresponsive
|
||||||
// Also, it's nice to have us shutdown at the same time as the main application
|
// Also, it's nice to have us shutdown at the same time as the main application
|
||||||
|
Swt.onShutdown(new Runnable() {
|
||||||
// During compile time (for production), this class is not compiled, and instead is copied over as a pre-compiled file
|
@Override
|
||||||
// This is so we don't have to rely on having SWT as part of the classpath during build.
|
public
|
||||||
try {
|
void run() {
|
||||||
Class<?> clazz = Class.forName("dorkbox.systemTray.swt.Swt");
|
if (systemTray != null) {
|
||||||
Method method = clazz.getMethod("onShutdown", Runnable.class);
|
systemTray.shutdown();
|
||||||
Object o = method.invoke(null, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public
|
|
||||||
void run() {
|
|
||||||
if (systemTray != null) {
|
|
||||||
systemTray.shutdown();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
} catch (Throwable e) {
|
|
||||||
if (DEBUG) {
|
|
||||||
logger.error("Cannot initialize SWT", e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
logger.error("Unable to insert shutdown hook into SWT. Please create an issue with your OS and Java " +
|
});
|
||||||
"version so we may further investigate this issue.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ import dorkbox.systemTray.linux.jna.GEventCallback;
|
|||||||
import dorkbox.systemTray.linux.jna.GdkEventButton;
|
import dorkbox.systemTray.linux.jna.GdkEventButton;
|
||||||
import dorkbox.systemTray.linux.jna.Gobject;
|
import dorkbox.systemTray.linux.jna.Gobject;
|
||||||
import dorkbox.systemTray.linux.jna.Gtk;
|
import dorkbox.systemTray.linux.jna.Gtk;
|
||||||
import javafx.application.Platform;
|
import dorkbox.systemTray.util.JavaFX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for handling all system tray interactions via GTK.
|
* Class for handling all system tray interactions via GTK.
|
||||||
@ -89,7 +89,7 @@ class GtkSystemTray extends GtkTypeSystemTray {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (SystemTray.isJavaFxLoaded) {
|
if (SystemTray.isJavaFxLoaded) {
|
||||||
if (!Platform.isFxApplicationThread()) {
|
if (!JavaFX.isEventThread()) {
|
||||||
try {
|
try {
|
||||||
blockUntilStarted.await(10, TimeUnit.SECONDS);
|
blockUntilStarted.await(10, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
@ -18,7 +18,6 @@ package dorkbox.systemTray.linux.jna;
|
|||||||
import static dorkbox.systemTray.SystemTray.logger;
|
import static dorkbox.systemTray.SystemTray.logger;
|
||||||
import static dorkbox.systemTray.linux.jna.Gobject.g_idle_add;
|
import static dorkbox.systemTray.linux.jna.Gobject.g_idle_add;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -27,6 +26,8 @@ import com.sun.jna.Function;
|
|||||||
import com.sun.jna.Pointer;
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
import dorkbox.systemTray.SystemTray;
|
import dorkbox.systemTray.SystemTray;
|
||||||
|
import dorkbox.systemTray.util.JavaFX;
|
||||||
|
import dorkbox.systemTray.util.Swt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bindings for gtk 2 or 3
|
* bindings for gtk 2 or 3
|
||||||
@ -50,8 +51,8 @@ class Gtk {
|
|||||||
private static boolean alreadyRunningGTK = false;
|
private static boolean alreadyRunningGTK = false;
|
||||||
private static boolean isLoaded = false;
|
private static boolean isLoaded = false;
|
||||||
|
|
||||||
private static Method swtDispatchMethod = null;
|
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 | grep gtk
|
||||||
|
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 | grep gtk
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We can have GTK v3 or v2.
|
* We can have GTK v3 or v2.
|
||||||
@ -60,10 +61,6 @@ class Gtk {
|
|||||||
* JavaFX uses GTK2, and we can't load GTK3 if GTK2 symbols are loaded
|
* JavaFX uses GTK2, and we can't load GTK3 if GTK2 symbols are loaded
|
||||||
* SWT uses GTK2 or GTK3. We do not work with the GTK3 version of SWT.
|
* SWT uses GTK2 or GTK3. We do not work with the GTK3 version of SWT.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 | grep gtk
|
|
||||||
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 | grep gtk
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
boolean shouldUseGtk2 = SystemTray.FORCE_GTK2;
|
boolean shouldUseGtk2 = SystemTray.FORCE_GTK2;
|
||||||
|
|
||||||
@ -159,8 +156,10 @@ class Gtk {
|
|||||||
private static volatile boolean started = false;
|
private static volatile boolean started = false;
|
||||||
|
|
||||||
// have to save these in a field to prevent GC on the objects (since they go out-of-scope from java)
|
// have to save these in a field to prevent GC on the objects (since they go out-of-scope from java)
|
||||||
|
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
|
||||||
private static final LinkedList<Object> gtkCallbacks = new LinkedList<Object>();
|
private static final LinkedList<Object> gtkCallbacks = new LinkedList<Object>();
|
||||||
|
|
||||||
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
private static Thread gtkUpdateThread = null;
|
private static Thread gtkUpdateThread = null;
|
||||||
|
|
||||||
public static final int FALSE = 0;
|
public static final int FALSE = 0;
|
||||||
@ -228,20 +227,6 @@ class Gtk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SystemTray.isSwtLoaded) {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName("dorkbox.systemTray.swt.Swt");
|
|
||||||
swtDispatchMethod = clazz.getMethod("dispatch", Runnable.class);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
if (SystemTray.DEBUG) {
|
|
||||||
logger.error("Cannot initialize SWT dispatch", e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
logger.error("Unable to call into dispatch method for SWT. Please create an issue with your OS and Java " +
|
|
||||||
"version so we may further investigate this issue.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -253,22 +238,16 @@ class Gtk {
|
|||||||
// SWT/JavaFX
|
// SWT/JavaFX
|
||||||
|
|
||||||
if (SystemTray.isJavaFxLoaded) {
|
if (SystemTray.isJavaFxLoaded) {
|
||||||
if (javafx.application.Platform.isFxApplicationThread()) {
|
if (JavaFX.isEventThread()) {
|
||||||
// Run directly on the JavaFX event thread
|
// Run directly on the JavaFX event thread
|
||||||
runnable.run();
|
runnable.run();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
javafx.application.Platform.runLater(runnable);
|
JavaFX.dispatch(runnable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (SystemTray.isSwtLoaded) {
|
else if (SystemTray.isSwtLoaded) {
|
||||||
try {
|
Swt.dispatch(runnable);
|
||||||
swtDispatchMethod.invoke(null, runnable);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Unable to call into dispatch method for SWT. Please create an issue with your OS and Java " +
|
|
||||||
"version so we may further investigate this issue.");
|
|
||||||
throw new RuntimeException("Unable to invoke required SWT method");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -335,17 +314,6 @@ class Gtk {
|
|||||||
*/
|
*/
|
||||||
private static native void gtk_main_quit();
|
private static native void gtk_main_quit();
|
||||||
|
|
||||||
private static native void gdk_threads_init();
|
|
||||||
|
|
||||||
// tricky business. Only when using SWT/JavaFX, because they do it wrong.
|
|
||||||
/**
|
|
||||||
* @return TRUE to run this callback again, FALSE to remove from the list of event sources (and not call it again)
|
|
||||||
*/
|
|
||||||
private static native int gdk_threads_add_idle(FuncCallback callback, Pointer data);
|
|
||||||
private static native void gdk_threads_enter();
|
|
||||||
private static native void gdk_threads_leave();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -371,7 +339,6 @@ class Gtk {
|
|||||||
|
|
||||||
public static native void gtk_label_set_use_markup(Pointer label, int gboolean);
|
public static native void gtk_label_set_use_markup(Pointer label, int gboolean);
|
||||||
|
|
||||||
public static native Pointer gtk_status_icon_new_from_icon_name(String iconName);;
|
|
||||||
public static native Pointer gtk_status_icon_new();
|
public static native Pointer gtk_status_icon_new();
|
||||||
|
|
||||||
public static native void gtk_status_icon_set_from_file(Pointer widget, String label);
|
public static native void gtk_status_icon_set_from_file(Pointer widget, String label);
|
||||||
@ -397,8 +364,6 @@ class Gtk {
|
|||||||
|
|
||||||
public static native void gtk_container_remove(Pointer menu, Pointer subItem);
|
public static native void gtk_container_remove(Pointer menu, Pointer subItem);
|
||||||
|
|
||||||
public static native void gtk_widget_show(Pointer widget);
|
|
||||||
|
|
||||||
public static native void gtk_widget_show_all(Pointer widget);
|
public static native void gtk_widget_show_all(Pointer widget);
|
||||||
|
|
||||||
public static native void gtk_widget_destroy(Pointer widget);
|
public static native void gtk_widget_destroy(Pointer widget);
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 dorkbox, llc
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package dorkbox.systemTray.swt;
|
|
||||||
|
|
||||||
import org.eclipse.swt.SWT;
|
|
||||||
import org.eclipse.swt.widgets.Display;
|
|
||||||
import org.eclipse.swt.widgets.Event;
|
|
||||||
import org.eclipse.swt.widgets.Listener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SWT system tray types are just GTK trays.
|
|
||||||
* <p>
|
|
||||||
* This isn't possible with reflection - so we compile it AHEAD of time and save the bytecode (which is then included with the release)
|
|
||||||
* We **COULD** do some ASM/Bytecode generation, but why bother with even more libraries when it's just as easy to include it pre-compiled.
|
|
||||||
*/
|
|
||||||
public
|
|
||||||
class Swt {
|
|
||||||
public static
|
|
||||||
void dispatch(final Runnable runnable) {
|
|
||||||
Display.getDefault().asyncExec(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static
|
|
||||||
void onShutdown(final Runnable runnable) {
|
|
||||||
Display.getCurrent().getShells()[0].addListener(SWT.Close, new Listener() {
|
|
||||||
@Override
|
|
||||||
public
|
|
||||||
void handleEvent(final Event event) {
|
|
||||||
runnable.run();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
110
src/dorkbox/systemTray/util/JavaFX.java
Normal file
110
src/dorkbox/systemTray/util/JavaFX.java
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package dorkbox.systemTray.util;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import dorkbox.systemTray.SystemTray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for JavaFX.
|
||||||
|
* <p>
|
||||||
|
* We use reflection for these methods so that we can compile everything under Java 1.6 (which doesn't have JavaFX).
|
||||||
|
*/
|
||||||
|
public
|
||||||
|
class JavaFX {
|
||||||
|
|
||||||
|
// Methods are cached for performance
|
||||||
|
private static Method isEventThread;
|
||||||
|
private static Method dispatchMethod;
|
||||||
|
|
||||||
|
public static
|
||||||
|
boolean isLoaded() throws Exception {
|
||||||
|
// JavaFX Java7,8 is GTK2 only. Java9 can have it be GTK3 if -Djdk.gtk.version=3 is specified
|
||||||
|
// see http://mail.openjdk.java.net/pipermail/openjfx-dev/2016-May/019100.html
|
||||||
|
|
||||||
|
// this is important to use reflection, because if JavaFX is not being used, calling getToolkit() will initialize it...
|
||||||
|
java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
|
||||||
|
m.setAccessible(true);
|
||||||
|
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
||||||
|
return (null != m.invoke(cl, "com.sun.javafx.tk.Toolkit")) || (null != m.invoke(cl, "javafx.application.Application"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
void dispatch(final Runnable runnable) {
|
||||||
|
// javafx.application.Platform.runLater(runnable);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (dispatchMethod == null) {
|
||||||
|
Class<?> clazz = Class.forName("javafx.application.Platform");
|
||||||
|
dispatchMethod = clazz.getMethod("runLater");
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchMethod.invoke(null, runnable);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
SystemTray.logger.error("Cannot initialize JavaFX", e);
|
||||||
|
}
|
||||||
|
SystemTray.logger.error("Unable to execute JavaFX runLater(). Please create an issue with your OS and Java " +
|
||||||
|
"version so we may further investigate this issue.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
boolean isEventThread() {
|
||||||
|
// javafx.application.Platform.isFxApplicationThread();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isEventThread == null) {
|
||||||
|
Class<?> clazz = Class.forName("javafx.application.Platform");
|
||||||
|
isEventThread = clazz.getMethod("isFxApplicationThread");
|
||||||
|
}
|
||||||
|
return (Boolean) isEventThread.invoke(null);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
SystemTray.logger.error("Cannot initialize JavaFX", e);
|
||||||
|
}
|
||||||
|
SystemTray.logger.error("Unable to check if JavaFX is in the event thread. Please create an issue with your OS and Java " +
|
||||||
|
"version so we may further investigate this issue.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
void onShutdown(final Runnable runnable) {
|
||||||
|
// com.sun.javafx.tk.Toolkit.getToolkit()
|
||||||
|
// .addShutdownHook(runnable);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> clazz = Class.forName("com.sun.javafx.tk.Toolkit");
|
||||||
|
Method method = clazz.getMethod("getToolkit");
|
||||||
|
Object o = method.invoke(null);
|
||||||
|
Method m = o.getClass()
|
||||||
|
.getMethod("addShutdownHook", Runnable.class);
|
||||||
|
m.invoke(o, runnable);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
if (SystemTray.DEBUG) {
|
||||||
|
SystemTray.logger.error("Cannot initialize JavaFX", e);
|
||||||
|
}
|
||||||
|
SystemTray.logger.error("Unable to insert shutdown hook into JavaFX. Please create an issue with your OS and Java " +
|
||||||
|
"version so we may further investigate this issue.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
58
src/dorkbox/systemTray/util/Swt.java
Normal file
58
src/dorkbox/systemTray/util/Swt.java
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package dorkbox.systemTray.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for SWT.
|
||||||
|
* <p>
|
||||||
|
* SWT system tray types are just GTK trays.
|
||||||
|
* <p>
|
||||||
|
* Creating custom methods for a class is not possible with reflection - so we compile it AHEAD of time as Java 1.6, and save the bytecode
|
||||||
|
* (which is then included with the release)
|
||||||
|
* <p>
|
||||||
|
* We **COULD** do some ASM/Bytecode generation, but why bother with even more libraries when it's just as easy to include it pre-compiled.
|
||||||
|
*/
|
||||||
|
public
|
||||||
|
class Swt {
|
||||||
|
public static
|
||||||
|
boolean isLoaded() throws Exception {
|
||||||
|
// maybe we should load the SWT version? (In order for us to work with SWT, BOTH must be GTK2!!
|
||||||
|
// SWT is GTK2, but if -DSWT_GTK3=1 is specified, it can be GTK3
|
||||||
|
|
||||||
|
java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
|
||||||
|
m.setAccessible(true);
|
||||||
|
ClassLoader cl = ClassLoader.getSystemClassLoader();
|
||||||
|
return null != m.invoke(cl, "org.eclipse.swt.widgets.Display");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
void dispatch(final Runnable runnable) {
|
||||||
|
org.eclipse.swt.widgets.Display.getCurrent()
|
||||||
|
.asyncExec(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static
|
||||||
|
void onShutdown(final Runnable runnable) {
|
||||||
|
org.eclipse.swt.widgets.Display.getCurrent()
|
||||||
|
.getShells()[0].addListener(org.eclipse.swt.SWT.Close, new org.eclipse.swt.widgets.Listener() {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
void handleEvent(final org.eclipse.swt.widgets.Event event) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user