SWT no longer using reflection (using trampoline class for access)
This commit is contained in:
parent
01d92c0a86
commit
23ffd02b65
@ -15,15 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.swt;
|
package dorkbox.util.swt;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
|
||||||
import org.eclipse.swt.SWT;
|
|
||||||
import org.eclipse.swt.widgets.Display;
|
|
||||||
|
|
||||||
import dorkbox.os.OS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods for SWT. SWT is always available for compiling, so it is not necessary to use reflection to compile it.
|
* Utility methods for SWT. SWT is always available for compiling, so it is not necessary to use reflection to compile it.
|
||||||
* <p>
|
* <p>
|
||||||
@ -35,33 +29,13 @@ class Swt {
|
|||||||
public final static boolean isGtk3;
|
public final static boolean isGtk3;
|
||||||
private static final int version;
|
private static final int version;
|
||||||
|
|
||||||
private static final Display currentDisplay;
|
// NOTE: This class cannot have SWT **ANYTHING** in it
|
||||||
private static final Thread currentDisplayThread;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// There is a silly amount of redirection, simply because we have to be able to access SWT, but only if it's in use.
|
// There is a silly amount of redirection, simply because we have to be able to access SWT, but only if it's in use.
|
||||||
|
|
||||||
// Since this class is the place other code interacts with, we can use SWT stuff if necessary without loading/linking
|
// Since this class is the place other code interacts with, we can use SWT stuff if necessary without loading/linking
|
||||||
// the SWT classes by accident
|
// the SWT classes by accident
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
boolean isSwtLoadable_ = isLoadable();
|
|
||||||
|
|
||||||
version = SWT.getVersion();
|
|
||||||
isLoaded = isSwtLoadable_;
|
|
||||||
isGtk3 = isSwtLoadable_ && isGtk3();
|
|
||||||
|
|
||||||
|
|
||||||
// we MUST save this on init, otherwise it is "null" when methods are run from the swing EDT.
|
|
||||||
currentDisplay = org.eclipse.swt.widgets.Display.getCurrent();
|
|
||||||
currentDisplayThread = currentDisplay.getThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This uses reflection to check if SWT is loadable and if certain classes are available.
|
|
||||||
* @return true if SWT is loadable
|
|
||||||
*/
|
|
||||||
static boolean isLoadable() {
|
|
||||||
Class<?> swtErrorClass = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
|
Class<?> swtErrorClass = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
@ -79,78 +53,20 @@ class Swt {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (swtErrorClass != null) {
|
if (swtErrorClass != null) {
|
||||||
try {
|
// this means that SWT is available in the system at runtime. We use the error class because that DOES NOT intitialize anything
|
||||||
return org.eclipse.swt.SWT.isLoadable();
|
boolean isSwtLoadable_ = SwtAccess.isLoadable();
|
||||||
} catch (Exception ignored) {
|
version = SwtAccess.getVersion();
|
||||||
}
|
isLoaded = isSwtLoadable_;
|
||||||
}
|
isGtk3 = isSwtLoadable_ && SwtAccess.isGtk3();
|
||||||
|
|
||||||
return false;
|
SwtAccess.init();
|
||||||
|
} else {
|
||||||
|
version = 0;
|
||||||
|
isLoaded = false;
|
||||||
|
isGtk3 = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is only necessary for linux.
|
|
||||||
*
|
|
||||||
* @return true if SWT is GTK3. False if SWT is GTK2. If for some reason we DO NOT KNOW, then we return false (GTK2).
|
|
||||||
*/
|
|
||||||
static boolean isGtk3() {
|
|
||||||
if (!OS.isLinux()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// required to use reflection, because this is an internal class
|
|
||||||
final String SWT_INTERNAL_CLASS = "org.eclipse.swt.internal.gtk.OS";
|
|
||||||
Class<?> osClass = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
|
|
||||||
@Override
|
|
||||||
public
|
|
||||||
Class<?> run() {
|
|
||||||
try {
|
|
||||||
return Class.forName(SWT_INTERNAL_CLASS, true, ClassLoader.getSystemClassLoader());
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return Class.forName(SWT_INTERNAL_CLASS, true, Thread.currentThread().getContextClassLoader());
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
if (osClass == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Class<?> clazz = osClass;
|
|
||||||
Method method = AccessController.doPrivileged(new PrivilegedAction<Method>() {
|
|
||||||
@Override
|
|
||||||
public
|
|
||||||
Method run() {
|
|
||||||
try {
|
|
||||||
return clazz.getMethod("gtk_major_version");
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (method == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int version = 0;
|
|
||||||
try {
|
|
||||||
version = ((Number)method.invoke(osClass)).intValue();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
// this method doesn't exist.
|
|
||||||
}
|
|
||||||
|
|
||||||
return version == 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static
|
public static
|
||||||
int getVersion() {
|
int getVersion() {
|
||||||
return version;
|
return version;
|
||||||
@ -158,27 +74,16 @@ class Swt {
|
|||||||
|
|
||||||
public static
|
public static
|
||||||
void dispatch(final Runnable runnable) {
|
void dispatch(final Runnable runnable) {
|
||||||
currentDisplay.syncExec(runnable);
|
SwtAccess.dispatch(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static
|
public static
|
||||||
boolean isEventThread() {
|
boolean isEventThread() {
|
||||||
return Thread.currentThread() == currentDisplayThread;
|
return SwtAccess.isEventThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static
|
public static
|
||||||
void onShutdown(final Runnable runnable) {
|
void onShutdown(final Runnable runnable) {
|
||||||
// currentDisplay.getShells() must only be called inside the event thread!
|
SwtAccess.onShutdown(runnable);
|
||||||
if (isEventThread()) {
|
|
||||||
SwtAccess.onShutdown(currentDisplay, runnable);
|
|
||||||
} else {
|
|
||||||
dispatch(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public
|
|
||||||
void run() {
|
|
||||||
SwtAccess.onShutdown(currentDisplay, runnable);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,31 @@
|
|||||||
package dorkbox.util.swt;
|
package dorkbox.util.swt;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
|
||||||
|
import dorkbox.os.OS;
|
||||||
|
|
||||||
public
|
public
|
||||||
class SwtAccess {
|
class SwtAccess {
|
||||||
|
private static Display currentDisplay = null;
|
||||||
|
private static Thread currentDisplayThread = null;
|
||||||
|
|
||||||
|
public static
|
||||||
|
void init() {
|
||||||
|
// we MUST save this on init, otherwise it is "null" when methods are run from the swing EDT.
|
||||||
|
currentDisplay = org.eclipse.swt.widgets.Display.getCurrent();
|
||||||
|
currentDisplayThread = currentDisplay.getThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
boolean isLoadable() {
|
||||||
|
return org.eclipse.swt.SWT.isLoadable();
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void onShutdown(final org.eclipse.swt.widgets.Display currentDisplay, final Runnable runnable) {
|
void onShutdown(final org.eclipse.swt.widgets.Display currentDisplay, final Runnable runnable) {
|
||||||
// currentDisplay.getShells() must only be called inside the event thread!
|
// currentDisplay.getShells() must only be called inside the event thread!
|
||||||
@ -15,4 +39,97 @@ class SwtAccess {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int getVersion() {
|
||||||
|
return SWT.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is only necessary for linux.
|
||||||
|
*
|
||||||
|
* @return true if SWT is GTK3. False if SWT is GTK2. If for some reason we DO NOT KNOW, then we return false (GTK2).
|
||||||
|
*/
|
||||||
|
static boolean isGtk3() {
|
||||||
|
if (!OS.isLinux()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// required to use reflection, because this is an internal class!
|
||||||
|
final String SWT_INTERNAL_CLASS = "org.eclipse.swt.internal.gtk.OS";
|
||||||
|
Class<?> osClass = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
Class<?> run() {
|
||||||
|
try {
|
||||||
|
return Class.forName(SWT_INTERNAL_CLASS, true, ClassLoader.getSystemClassLoader());
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Class.forName(SWT_INTERNAL_CLASS, true, Thread.currentThread().getContextClassLoader());
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (osClass == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Class<?> clazz = osClass;
|
||||||
|
Method method = AccessController.doPrivileged(new PrivilegedAction<Method>() {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
Method run() {
|
||||||
|
try {
|
||||||
|
return clazz.getMethod("gtk_major_version");
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (method == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int version = 0;
|
||||||
|
try {
|
||||||
|
version = ((Number)method.invoke(osClass)).intValue();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
// this method doesn't exist.
|
||||||
|
}
|
||||||
|
|
||||||
|
return version == 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void dispatch(final Runnable runnable) {
|
||||||
|
currentDisplay.syncExec(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
boolean isEventThread() {
|
||||||
|
return Thread.currentThread() == currentDisplayThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void onShutdown(final Runnable runnable) {
|
||||||
|
// currentDisplay.getShells() must only be called inside the event thread!
|
||||||
|
if (isEventThread()) {
|
||||||
|
SwtAccess.onShutdown(currentDisplay, runnable);
|
||||||
|
} else {
|
||||||
|
dispatch(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
void run() {
|
||||||
|
SwtAccess.onShutdown(currentDisplay, runnable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user