Changed support for SWT, added GtkSupport.DISABLE_EVENT_LOOP to disable the creation of the native event loop (ie: if using SWT, which already does this)
This commit is contained in:
parent
5b8cbadb84
commit
b81995ab2b
|
@ -83,8 +83,6 @@ public interface Gtk extends Library {
|
|||
void gtk_main_quit();
|
||||
|
||||
void gdk_threads_init();
|
||||
void gdk_threads_enter();
|
||||
void gdk_threads_leave();
|
||||
|
||||
Pointer gtk_menu_new();
|
||||
Pointer gtk_menu_item_new();
|
||||
|
|
|
@ -15,45 +15,38 @@
|
|||
*/
|
||||
package dorkbox.util.jna.linux;
|
||||
|
||||
import dorkbox.util.Property;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public
|
||||
class GtkSupport {
|
||||
public static final boolean isSupported;
|
||||
private static final boolean hasSwt;
|
||||
|
||||
// RE: SWT
|
||||
// https://developer.gnome.org/glib/stable/glib-Deprecated-Thread-APIs.html#g-thread-init
|
||||
// Since version >= 2.24, threads can only init once. Multiple calls do nothing, and we can nest gtk_main()
|
||||
// in a nested loop.
|
||||
|
||||
private static volatile boolean started = false;
|
||||
private static final ArrayBlockingQueue<Runnable> dispatchEvents = new ArrayBlockingQueue<Runnable>(256);
|
||||
private static volatile Thread gtkDispatchThread;
|
||||
|
||||
@Property
|
||||
/** Disables the GTK event loop, if you are already creating one in SWT/etc. */
|
||||
public static boolean DISABLE_EVENT_LOOP = false;
|
||||
|
||||
static {
|
||||
boolean hasSupport = false;
|
||||
boolean hasSWT_ = false;
|
||||
try {
|
||||
if (Gtk.INSTANCE != null && Gobject.INSTANCE != null && GThread.INSTANCE != null) {
|
||||
hasSupport = true;
|
||||
|
||||
try {
|
||||
Class<?> swtClass = Class.forName("org.eclipse.swt.widgets.Display");
|
||||
if (swtClass != null) {
|
||||
hasSWT_ = true;
|
||||
}
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
|
||||
|
||||
// prep for the event loop.
|
||||
// since SWT uses one already, it's not necessary to have two.
|
||||
if (!hasSWT_) {
|
||||
Gtk instance = Gtk.INSTANCE;
|
||||
instance.gtk_init(0, null);
|
||||
GThread.INSTANCE.g_thread_init(null);
|
||||
instance.gdk_threads_init();
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
isSupported = hasSupport;
|
||||
hasSwt = hasSWT_;
|
||||
}
|
||||
|
||||
public static
|
||||
|
@ -62,9 +55,26 @@ class GtkSupport {
|
|||
if (!started) {
|
||||
started = true;
|
||||
|
||||
// startup the GTK GUI event loop. There can be multiple/nested loops.
|
||||
// since SWT uses one already, it's not necessary to have two.
|
||||
if (!hasSwt) {
|
||||
gtkDispatchThread = new Thread() {
|
||||
@Override
|
||||
public
|
||||
void run() {
|
||||
while (started) {
|
||||
try {
|
||||
final Runnable take = dispatchEvents.take();
|
||||
take.run();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
gtkDispatchThread.setName("GTK Event Loop");
|
||||
gtkDispatchThread.start();
|
||||
|
||||
|
||||
if (!DISABLE_EVENT_LOOP) {
|
||||
// startup the GTK GUI event loop. There can be multiple/nested loops.
|
||||
final CountDownLatch blockUntilStarted = new CountDownLatch(1);
|
||||
Thread gtkUpdateThread = new Thread() {
|
||||
@Override
|
||||
|
@ -74,17 +84,21 @@ class GtkSupport {
|
|||
|
||||
// notify our main thread to continue
|
||||
blockUntilStarted.countDown();
|
||||
instance.gdk_threads_enter();
|
||||
|
||||
|
||||
// prep for the event loop.
|
||||
instance.gdk_threads_init();
|
||||
instance.gtk_init(0, null);
|
||||
GThread.INSTANCE.g_thread_init(null);
|
||||
|
||||
instance.gtk_main();
|
||||
// MUST leave as well!
|
||||
instance.gdk_threads_leave();
|
||||
}
|
||||
};
|
||||
gtkUpdateThread.setName("GTK Event Loop");
|
||||
gtkUpdateThread.setName("GTK Event Loop (Native)");
|
||||
gtkUpdateThread.start();
|
||||
|
||||
try {
|
||||
// we CANNOT continue until the GTK thread has started! (ignored if SWT is used)
|
||||
// we CANNOT continue until the GTK thread has started!
|
||||
blockUntilStarted.await();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -93,11 +107,25 @@ class GtkSupport {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Best practices for GTK, is to call EVERYTHING for it on a SINGLE THREAD. This accomplishes that.
|
||||
*/
|
||||
public static
|
||||
void shutdownGui() {
|
||||
if (isSupported && !hasSwt) {
|
||||
Gtk.INSTANCE.gtk_main_quit();
|
||||
started = false;
|
||||
void dispatch(Runnable runnable) {
|
||||
try {
|
||||
dispatchEvents.put(runnable);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static
|
||||
void shutdownGui() {
|
||||
if (!DISABLE_EVENT_LOOP) {
|
||||
Gtk.INSTANCE.gtk_main_quit();
|
||||
}
|
||||
|
||||
started = false;
|
||||
gtkDispatchThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user