Fixed issues when running JavaFX or SWT on the swing EDT.

This commit is contained in:
nathan 2016-10-12 18:09:17 +02:00
parent bc4d22c586
commit 59669bc867
3 changed files with 78 additions and 26 deletions

View File

@ -26,6 +26,8 @@ import java.io.PrintStream;
import java.net.URL;
import java.util.concurrent.atomic.AtomicReference;
import javax.swing.SwingUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -573,10 +575,26 @@ class SystemTray implements Menu {
}
}
if (isJavaFxLoaded) {
// This will initialize javaFX dispatch methods
JavaFX.init();
}
else if (isSwtLoaded) {
// This will initialize swt dispatch methods
Swt.init();
}
// if it's native + linux, have to do GTK instead. Don't need to be on the dispatch thread though.
// _AwtTray must be constructed on the EDT...
if (OS.isLinux() && NativeUI.class.isAssignableFrom(trayType) && trayType == _AwtTray.class) {
if ((isJavaFxLoaded || isSwtLoaded) && SwingUtilities.isEventDispatchThread()) {
// oh boy! This WILL NOT WORK. Let the dev know
throw new RuntimeException("SystemTray initialization can not occur on the swing Event Dispatch Thread (EDT)");
}
// javaFX and SWT should not start on the EDT!!
// if it's linux + native menus must not start on the EDT!
// _AwtTray must be constructed on the EDT however...
if (isJavaFxLoaded || isSwtLoaded ||
(OS.isLinux() && NativeUI.class.isAssignableFrom(trayType) && trayType == _AwtTray.class)) {
try {
reference.set((Menu) trayType.getConstructors()[0].newInstance(systemTray));
logger.info("Successfully Loaded: {}", trayType.getSimpleName());
@ -619,7 +637,6 @@ class SystemTray implements Menu {
"configuration");
}
// These install a shutdown hook in JavaFX/SWT, so that when the main window is closed -- the system tray is ALSO closed.
if (ENABLE_SHUTDOWN_HOOK) {
if (isJavaFxLoaded) {

View File

@ -29,24 +29,47 @@ public
class JavaFX {
// Methods are cached for performance
private static Method isEventThread;
private static Method dispatchMethod;
private static final Method dispatchMethod;
private static final Method isEventThreadMethod;
public static
void dispatch(final Runnable runnable) {
// javafx.application.Platform.runLater(runnable);
static {
Method _isEventThreadMethod = null;
Method _dispatchMethod = null;
try {
if (dispatchMethod == null) {
Class<?> clazz = Class.forName("javafx.application.Platform");
dispatchMethod = clazz.getMethod("runLater");
}
Class<?> clazz = Class.forName("javafx.application.Platform");
_dispatchMethod = clazz.getMethod("runLater", Runnable.class);
dispatchMethod.invoke(null, runnable);
clazz = Class.forName("javafx.application.Platform");
_isEventThreadMethod = clazz.getMethod("isFxApplicationThread");
} catch (Throwable e) {
if (SystemTray.DEBUG) {
SystemTray.logger.error("Cannot initialize JavaFX", e);
}
}
dispatchMethod = _dispatchMethod;
isEventThreadMethod = _isEventThreadMethod;
}
public static
void init() {
// empty method to initialize class
if (dispatchMethod == null || isEventThreadMethod == null) {
SystemTray.logger.error("Unable to initialize JavaFX! Please create an issue with your OS and Java " +
"version so we may further investigate this issue.");
}
}
public static
void dispatch(final Runnable runnable) {
// javafx.application.Platform.runLater(runnable);
try {
dispatchMethod.invoke(null, runnable);
} catch (Throwable 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.");
}
@ -57,15 +80,8 @@ class JavaFX {
// javafx.application.Platform.isFxApplicationThread();
try {
if (isEventThread == null) {
Class<?> clazz = Class.forName("javafx.application.Platform");
isEventThread = clazz.getMethod("isFxApplicationThread");
}
return (Boolean) isEventThread.invoke(null);
return (Boolean) isEventThreadMethod.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.");
}

View File

@ -15,6 +15,10 @@
*/
package dorkbox.systemTray.util;
import static dorkbox.systemTray.SystemTray.logger;
import org.eclipse.swt.widgets.Display;
/**
* Utility methods for SWT.
* <p>
@ -22,16 +26,31 @@ package dorkbox.systemTray.util;
*/
public
class Swt {
private static final Display currentDisplay;
static {
// we have to save this, otherwise it is "null" when methods are run from the swing EDT.
currentDisplay = Display.getCurrent();
}
public static
void init() {
// empty method to initialize class
if (currentDisplay == null) {
logger.error("Unable to get the current display for SWT. Please create an issue with your OS and Java " +
"version so we may further investigate this issue.");
};
}
public static
void dispatch(final Runnable runnable) {
org.eclipse.swt.widgets.Display.getCurrent()
.syncExec(runnable);
currentDisplay.syncExec(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() {
currentDisplay.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) {