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 gtk_main_quit();
|
||||||
|
|
||||||
void gdk_threads_init();
|
void gdk_threads_init();
|
||||||
void gdk_threads_enter();
|
|
||||||
void gdk_threads_leave();
|
|
||||||
|
|
||||||
Pointer gtk_menu_new();
|
Pointer gtk_menu_new();
|
||||||
Pointer gtk_menu_item_new();
|
Pointer gtk_menu_item_new();
|
||||||
|
@ -15,45 +15,38 @@
|
|||||||
*/
|
*/
|
||||||
package dorkbox.util.jna.linux;
|
package dorkbox.util.jna.linux;
|
||||||
|
|
||||||
|
import dorkbox.util.Property;
|
||||||
|
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
public
|
public
|
||||||
class GtkSupport {
|
class GtkSupport {
|
||||||
public static final boolean isSupported;
|
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 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 {
|
static {
|
||||||
boolean hasSupport = false;
|
boolean hasSupport = false;
|
||||||
boolean hasSWT_ = false;
|
|
||||||
try {
|
try {
|
||||||
if (Gtk.INSTANCE != null && Gobject.INSTANCE != null && GThread.INSTANCE != null) {
|
if (Gtk.INSTANCE != null && Gobject.INSTANCE != null && GThread.INSTANCE != null) {
|
||||||
hasSupport = true;
|
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) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
isSupported = hasSupport;
|
isSupported = hasSupport;
|
||||||
hasSwt = hasSWT_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static
|
public static
|
||||||
@ -62,9 +55,26 @@ class GtkSupport {
|
|||||||
if (!started) {
|
if (!started) {
|
||||||
started = true;
|
started = true;
|
||||||
|
|
||||||
// startup the GTK GUI event loop. There can be multiple/nested loops.
|
gtkDispatchThread = new Thread() {
|
||||||
// since SWT uses one already, it's not necessary to have two.
|
@Override
|
||||||
if (!hasSwt) {
|
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);
|
final CountDownLatch blockUntilStarted = new CountDownLatch(1);
|
||||||
Thread gtkUpdateThread = new Thread() {
|
Thread gtkUpdateThread = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
@ -74,17 +84,21 @@ class GtkSupport {
|
|||||||
|
|
||||||
// notify our main thread to continue
|
// notify our main thread to continue
|
||||||
blockUntilStarted.countDown();
|
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();
|
instance.gtk_main();
|
||||||
// MUST leave as well!
|
|
||||||
instance.gdk_threads_leave();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
gtkUpdateThread.setName("GTK Event Loop");
|
gtkUpdateThread.setName("GTK Event Loop (Native)");
|
||||||
gtkUpdateThread.start();
|
gtkUpdateThread.start();
|
||||||
|
|
||||||
try {
|
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();
|
blockUntilStarted.await();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
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
|
public static
|
||||||
void shutdownGui() {
|
void dispatch(Runnable runnable) {
|
||||||
if (isSupported && !hasSwt) {
|
try {
|
||||||
Gtk.INSTANCE.gtk_main_quit();
|
dispatchEvents.put(runnable);
|
||||||
started = false;
|
} 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