SWT behaves better on linux now. Added Swt.isEventThread method

This commit is contained in:
nathan 2016-12-10 23:38:45 +01:00
parent 39ddd235f6
commit 9591362580
2 changed files with 43 additions and 53 deletions

View File

@ -234,7 +234,6 @@ class Gtk {
} }
}); });
if (SystemTray.isJavaFxLoaded) { if (SystemTray.isJavaFxLoaded) {
if (!JavaFX.isEventThread()) { if (!JavaFX.isEventThread()) {
try { try {
@ -255,10 +254,7 @@ class Gtk {
} }
} }
} else if (SystemTray.isSwtLoaded) { } else if (SystemTray.isSwtLoaded) {
if (SystemTray.FORCE_TRAY_TYPE != SystemTray.TrayType.GtkStatusIcon) { if (!Swt.isEventThread()) {
// GTK system tray has threading issues if we block here (because it is likely in the event thread)
// AppIndicator version doesn't have this problem
// we have to WAIT until all events are done processing, OTHERWISE we have initialization issues // we have to WAIT until all events are done processing, OTHERWISE we have initialization issues
try { try {
while (true) { while (true) {
@ -277,7 +273,6 @@ class Gtk {
} }
} }
} else { } else {
try { try {
// we have to WAIT until all events are done processing, OTHERWISE we have initialization issues // we have to WAIT until all events are done processing, OTHERWISE we have initialization issues
while (true) { while (true) {
@ -302,11 +297,9 @@ class Gtk {
*/ */
public static public static
void dispatch(final Runnable runnable) { void dispatch(final Runnable runnable) {
// FIXME: on mac, check -XstartOnFirstThread.. there are issues with javaFX (possibly SWT as well)
if (alreadyRunningGTK) { if (alreadyRunningGTK) {
// SWT/JavaFX
if (SystemTray.isJavaFxLoaded) { if (SystemTray.isJavaFxLoaded) {
// JavaFX only
if (JavaFX.isEventThread()) { if (JavaFX.isEventThread()) {
// Run directly on the JavaFX event thread // Run directly on the JavaFX event thread
runnable.run(); runnable.run();
@ -314,61 +307,50 @@ class Gtk {
else { else {
JavaFX.dispatch(runnable); JavaFX.dispatch(runnable);
} }
return;
} }
else if (SystemTray.isSwtLoaded) {
if (isDispatch) { if (SystemTray.isSwtLoaded) {
// Run directly on the dispatch thread if (Swt.isEventThread()) {
// Run directly on the SWT event thread. If it's not on the dispatch thread, we can use raw GTK to put it there
runnable.run(); runnable.run();
} else {
Swt.dispatch(new Runnable() {
@Override
public
void run() {
isDispatch = true;
try { return;
runnable.run();
} finally {
isDispatch = false;
}
}
});
} }
} }
} }
else {
// not swt/javafx
if (isDispatch) {
// Run directly on the dispatch thread
runnable.run();
} else {
final FuncCallback callback = new FuncCallback() {
@Override
public
int callback(final Pointer data) {
synchronized (gtkCallbacks) {
gtkCallbacks.removeFirst(); // now that we've 'handled' it, we can remove it from our callback list
isDispatch = true; // not javafx
// gtk/swt are **mostly** the same in how events are dispatched, so we can use "raw" gtk methods for SWT
if (isDispatch) {
// Run directly on the dispatch thread
runnable.run();
} else {
final FuncCallback callback = new FuncCallback() {
@Override
public
int callback(final Pointer data) {
synchronized (gtkCallbacks) {
gtkCallbacks.removeFirst(); // now that we've 'handled' it, we can remove it from our callback list
try { isDispatch = true;
runnable.run();
} finally { try {
isDispatch = false; runnable.run();
return Gtk.FALSE; // don't want to call this again } finally {
} isDispatch = false;
return Gtk.FALSE; // don't want to call this again
} }
} }
};
synchronized (gtkCallbacks) {
gtkCallbacks.offer(callback); // prevent GC from collecting this object before it can be called
// the correct way to do it. Add with a slightly higher value
gdk_threads_add_idle_full(100, callback, null, null);
} }
};
synchronized (gtkCallbacks) {
gtkCallbacks.offer(callback); // prevent GC from collecting this object before it can be called
// the correct way to do it. Add with a slightly higher value
gdk_threads_add_idle_full(100, callback, null, null);
} }
} }
} }

View File

@ -27,10 +27,13 @@ import org.eclipse.swt.widgets.Display;
public public
class Swt { class Swt {
private static final Display currentDisplay; private static final Display currentDisplay;
private static final Thread currentDisplayThread;
static { static {
// we have to save this, otherwise it is "null" when methods are run from the swing EDT. // we MUST save this, otherwise it is "null" when methods are run from the swing EDT.
currentDisplay = Display.getCurrent(); currentDisplay = Display.getCurrent();
currentDisplayThread = currentDisplay.getThread();
} }
@ -48,6 +51,11 @@ class Swt {
currentDisplay.syncExec(runnable); currentDisplay.syncExec(runnable);
} }
public static
boolean isEventThread() {
return Thread.currentThread() == currentDisplayThread;
}
public static public static
void onShutdown(final Runnable runnable) { void onShutdown(final Runnable runnable) {
currentDisplay.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() {