Added support for detecting if javaFX already started the GTK event loop (and hooking into the right places for shutdown if it does).
This commit is contained in:
parent
2e692733b3
commit
56f4bac16a
|
@ -58,7 +58,7 @@ interface Gtk extends Library {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gtk_init(int argc, String[] argv);
|
boolean gtk_init_check(int argc, String[] argv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the main loop until gtk_main_quit() is called. You can nest calls to gtk_main(). In that case gtk_main_quit() will make the
|
* Runs the main loop until gtk_main_quit() is called. You can nest calls to gtk_main(). In that case gtk_main_quit() will make the
|
||||||
|
@ -66,6 +66,10 @@ interface Gtk extends Library {
|
||||||
*/
|
*/
|
||||||
void gtk_main();
|
void gtk_main();
|
||||||
|
|
||||||
|
|
||||||
|
/** sks for the current nesting level of the main loop. Useful to determine (at startup) if GTK is already runnign */
|
||||||
|
int gtk_main_level();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the innermost invocation of the main loop return when it regains control. ONLY CALL FROM THE GtkSupport class, UNLESS you know
|
* Makes the innermost invocation of the main loop return when it regains control. ONLY CALL FROM THE GtkSupport class, UNLESS you know
|
||||||
* what you're doing!
|
* what you're doing!
|
||||||
|
@ -74,8 +78,8 @@ interface Gtk extends Library {
|
||||||
|
|
||||||
void gdk_threads_init();
|
void gdk_threads_init();
|
||||||
|
|
||||||
|
// tricky business. This should only be in the dispatch thread
|
||||||
void gdk_threads_enter();
|
void gdk_threads_enter();
|
||||||
|
|
||||||
void gdk_threads_leave();
|
void gdk_threads_leave();
|
||||||
|
|
||||||
Pointer gtk_menu_new();
|
Pointer gtk_menu_new();
|
||||||
|
|
|
@ -44,15 +44,17 @@ class GtkSupport {
|
||||||
|
|
||||||
public static volatile boolean isGtk2 = false;
|
public static volatile boolean isGtk2 = false;
|
||||||
|
|
||||||
|
private static volatile boolean alreadyRunningGTK = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for GTK, because we could have v3 or v2.
|
* Helper for GTK, because we could have v3 or v2.
|
||||||
*
|
*
|
||||||
* Observations: SWT & JavaFX both use GTK2, and we can't load GTK3 if GTK2 symbols are loaded
|
* Observations: JavaFX uses GTK2, and we can't load GTK3 if GTK2 symbols are loaded
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("Duplicates")
|
@SuppressWarnings("Duplicates")
|
||||||
public static
|
public static
|
||||||
Gtk get() {
|
Gtk get() {
|
||||||
Object library;
|
Gtk library;
|
||||||
|
|
||||||
boolean shouldUseGtk2 = GtkSupport.FORCE_GTK2;
|
boolean shouldUseGtk2 = GtkSupport.FORCE_GTK2;
|
||||||
|
|
||||||
|
@ -60,10 +62,14 @@ class GtkSupport {
|
||||||
if (shouldUseGtk2) {
|
if (shouldUseGtk2) {
|
||||||
try {
|
try {
|
||||||
gtk_status_icon_position_menu = Function.getFunction("gtk-x11-2.0", "gtk_status_icon_position_menu");
|
gtk_status_icon_position_menu = Function.getFunction("gtk-x11-2.0", "gtk_status_icon_position_menu");
|
||||||
library = Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
library = (Gtk) Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
||||||
if (library != null) {
|
if (library != null) {
|
||||||
isGtk2 = true;
|
isGtk2 = true;
|
||||||
return (Gtk) library;
|
|
||||||
|
// when running inside of JavaFX, this will be '1'. All other times this should be '0'
|
||||||
|
// when it's '1', it means that someone else has stared GTK -- so we DO NOT NEED TO.
|
||||||
|
alreadyRunningGTK = library.gtk_main_level() != 0;
|
||||||
|
return library;
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
|
@ -74,9 +80,12 @@ class GtkSupport {
|
||||||
// appindicator3 requires GTK3
|
// appindicator3 requires GTK3
|
||||||
try {
|
try {
|
||||||
gtk_status_icon_position_menu = Function.getFunction("libgtk-3.so.0", "gtk_status_icon_position_menu");
|
gtk_status_icon_position_menu = Function.getFunction("libgtk-3.so.0", "gtk_status_icon_position_menu");
|
||||||
library = Native.loadLibrary("libgtk-3.so.0", Gtk.class);
|
library = (Gtk) Native.loadLibrary("libgtk-3.so.0", Gtk.class);
|
||||||
if (library != null) {
|
if (library != null) {
|
||||||
return (Gtk) library;
|
// when running inside of JavaFX, this will be '1'. All other times this should be '0'
|
||||||
|
// when it's '1', it means that someone else has stared GTK -- so we DO NOT NEED TO.
|
||||||
|
alreadyRunningGTK = library.gtk_main_level() != 0;
|
||||||
|
return library;
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
|
@ -84,10 +93,14 @@ class GtkSupport {
|
||||||
// appindicator1 requires GTK2
|
// appindicator1 requires GTK2
|
||||||
try {
|
try {
|
||||||
gtk_status_icon_position_menu = Function.getFunction("gtk-x11-2.0", "gtk_status_icon_position_menu");
|
gtk_status_icon_position_menu = Function.getFunction("gtk-x11-2.0", "gtk_status_icon_position_menu");
|
||||||
library = Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
library = (Gtk) Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
||||||
if (library != null) {
|
if (library != null) {
|
||||||
isGtk2 = true;
|
isGtk2 = true;
|
||||||
return (Gtk) library;
|
|
||||||
|
// when running inside of JavaFX, this will be '1'. All other times this should be '0'
|
||||||
|
// when it's '1', it means that someone else has stared GTK -- so we DO NOT NEED TO.
|
||||||
|
alreadyRunningGTK = library.gtk_main_level() != 0;
|
||||||
|
return library;
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
|
@ -99,9 +112,12 @@ class GtkSupport {
|
||||||
// start with version 3
|
// start with version 3
|
||||||
try {
|
try {
|
||||||
gtk_status_icon_position_menu = Function.getFunction("libgtk-3.so.0", "gtk_status_icon_position_menu");
|
gtk_status_icon_position_menu = Function.getFunction("libgtk-3.so.0", "gtk_status_icon_position_menu");
|
||||||
library = Native.loadLibrary("libgtk-3.so.0", Gtk.class);
|
library = (Gtk) Native.loadLibrary("libgtk-3.so.0", Gtk.class);
|
||||||
if (library != null) {
|
if (library != null) {
|
||||||
return (Gtk) library;
|
// when running inside of JavaFX, this will be '1'. All other times this should be '0'
|
||||||
|
// when it's '1', it means that someone else has stared GTK -- so we DO NOT NEED TO.
|
||||||
|
alreadyRunningGTK = library.gtk_main_level() != 0;
|
||||||
|
return library;
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
|
@ -109,10 +125,14 @@ class GtkSupport {
|
||||||
// now version 2
|
// now version 2
|
||||||
try {
|
try {
|
||||||
gtk_status_icon_position_menu = Function.getFunction("gtk-x11-2.0", "gtk_status_icon_position_menu");
|
gtk_status_icon_position_menu = Function.getFunction("gtk-x11-2.0", "gtk_status_icon_position_menu");
|
||||||
library = Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
library = (Gtk) Native.loadLibrary("gtk-x11-2.0", Gtk.class);
|
||||||
if (library != null) {
|
if (library != null) {
|
||||||
isGtk2 = true;
|
isGtk2 = true;
|
||||||
return (Gtk) library;
|
|
||||||
|
// when running inside of JavaFX, this will be '1'. All other times this should be '0'
|
||||||
|
// when it's '1', it means that someone else has stared GTK -- so we DO NOT NEED TO.
|
||||||
|
alreadyRunningGTK = library.gtk_main_level() != 0;
|
||||||
|
return library;
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
|
@ -127,6 +147,7 @@ class GtkSupport {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
started = true;
|
started = true;
|
||||||
|
|
||||||
|
// GTK specifies that we ONLY run from a single thread. This guarantees that.
|
||||||
gtkDispatchThread = new Thread() {
|
gtkDispatchThread = new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
|
@ -151,33 +172,41 @@ class GtkSupport {
|
||||||
|
|
||||||
|
|
||||||
// startup the GTK GUI event loop. There can be multiple/nested loops.
|
// startup the GTK GUI event loop. There can be multiple/nested loops.
|
||||||
final CountDownLatch blockUntilStarted = new CountDownLatch(1);
|
|
||||||
Thread gtkUpdateThread = new Thread() {
|
|
||||||
@Override
|
|
||||||
public
|
|
||||||
void run() {
|
|
||||||
Gtk instance = Gtk.INSTANCE;
|
|
||||||
|
|
||||||
// prep for the event loop.
|
// If JavaFX/SWT is used, this is UNNECESSARY
|
||||||
instance.gdk_threads_init();
|
if (!alreadyRunningGTK) {
|
||||||
instance.gtk_init(0, null);
|
// only necessary if we are the only GTK instance running...
|
||||||
GThread.INSTANCE.g_thread_init(null);
|
final CountDownLatch blockUntilStarted = new CountDownLatch(1);
|
||||||
|
Thread gtkUpdateThread = new Thread() {
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
void run() {
|
||||||
|
Gtk gtk = Gtk.INSTANCE;
|
||||||
|
|
||||||
// notify our main thread to continue
|
// prep for the event loop.
|
||||||
blockUntilStarted.countDown();
|
gtk.gdk_threads_init();
|
||||||
|
gtk.gdk_threads_enter();
|
||||||
|
|
||||||
// blocks unit quit
|
gtk.gtk_init_check(0, null);
|
||||||
instance.gtk_main();
|
|
||||||
|
// notify our main thread to continue
|
||||||
|
blockUntilStarted.countDown();
|
||||||
|
|
||||||
|
// blocks unit quit
|
||||||
|
// gtk.gtk_main();
|
||||||
|
|
||||||
|
gtk.gdk_threads_leave();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
gtkUpdateThread.setName("GTK Event Loop (Native)");
|
||||||
|
gtkUpdateThread.start();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// we CANNOT continue until the GTK thread has started!
|
||||||
|
blockUntilStarted.await();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
gtkUpdateThread.setName("GTK Event Loop (Native)");
|
|
||||||
gtkUpdateThread.start();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// we CANNOT continue until the GTK thread has started!
|
|
||||||
blockUntilStarted.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,7 +225,10 @@ class GtkSupport {
|
||||||
|
|
||||||
public static
|
public static
|
||||||
void shutdownGui() {
|
void shutdownGui() {
|
||||||
Gtk.INSTANCE.gtk_main_quit();
|
// If JavaFX/SWT is used, this is UNNECESSARY (an will break SWT/JavaFX shutdown)
|
||||||
|
if (!alreadyRunningGTK) {
|
||||||
|
Gtk.INSTANCE.gtk_main_quit();
|
||||||
|
}
|
||||||
|
|
||||||
started = false;
|
started = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user