GTK Event Dispatch main loop is now created in the 'non-deprecated' way.
This commit is contained in:
parent
c1520e1533
commit
5e3fec0909
30
src/dorkbox/util/jna/linux/GMainContext.java
Normal file
30
src/dorkbox/util/jna/linux/GMainContext.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package dorkbox.util.jna.linux;
|
||||||
|
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
|
public
|
||||||
|
class GMainContext extends GObject {
|
||||||
|
public
|
||||||
|
GMainContext() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public
|
||||||
|
GMainContext(Pointer p) {
|
||||||
|
super(p);
|
||||||
|
}
|
||||||
|
}
|
30
src/dorkbox/util/jna/linux/GMainLoop.java
Normal file
30
src/dorkbox/util/jna/linux/GMainLoop.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package dorkbox.util.jna.linux;
|
||||||
|
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
|
public
|
||||||
|
class GMainLoop extends GObject {
|
||||||
|
public
|
||||||
|
GMainLoop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public
|
||||||
|
GMainLoop(Pointer p) {
|
||||||
|
super(p);
|
||||||
|
}
|
||||||
|
}
|
47
src/dorkbox/util/jna/linux/GObject.java
Normal file
47
src/dorkbox/util/jna/linux/GObject.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package dorkbox.util.jna.linux;
|
||||||
|
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.PointerType;
|
||||||
|
|
||||||
|
public
|
||||||
|
class GObject extends PointerType {
|
||||||
|
public
|
||||||
|
GObject() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public
|
||||||
|
GObject(Pointer p) {
|
||||||
|
super(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected
|
||||||
|
void finalize() throws Throwable {
|
||||||
|
super.finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public
|
||||||
|
void ref() {
|
||||||
|
Gobject.g_object_ref(getPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
public
|
||||||
|
void unref() {
|
||||||
|
Gobject.g_object_unref(getPointer());
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,7 @@ class Gobject {
|
|||||||
|
|
||||||
// objdump -T /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 | grep block
|
// objdump -T /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 | grep block
|
||||||
|
|
||||||
|
public static native void g_object_ref(Pointer object);
|
||||||
public static native void g_object_unref(Pointer object);
|
public static native void g_object_unref(Pointer object);
|
||||||
|
|
||||||
public static native void g_object_force_floating(Pointer object);
|
public static native void g_object_force_floating(Pointer object);
|
||||||
|
@ -57,18 +57,6 @@ interface Gtk {
|
|||||||
|
|
||||||
Function gtk_status_icon_position_menu = GtkLoader.gtk_status_icon_position_menu;
|
Function gtk_status_icon_position_menu = GtkLoader.gtk_status_icon_position_menu;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a function to be called whenever there are no higher priority events pending. If the function returns FALSE it is automatically
|
|
||||||
* removed from the list of event sources and will not be called again.
|
|
||||||
* <p>
|
|
||||||
* This variant of g_idle_add_full() calls function with the GDK lock held. It can be thought of a MT-safe version for GTK+ widgets
|
|
||||||
* for the following use case, where you have to worry about idle_callback() running in thread A and accessing self after it has
|
|
||||||
* been finalized in thread B.
|
|
||||||
*/
|
|
||||||
int gdk_threads_add_idle_full(int priority, FuncCallback function, Pointer data, Pointer notify);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This would NORMALLY have a 2nd argument that is a String[] -- however JNA direct-mapping DOES NOT support this. We are lucky
|
* This would NORMALLY have a 2nd argument that is a String[] -- however JNA direct-mapping DOES NOT support this. We are lucky
|
||||||
* enough that we just pass 'null' as the second argument, therefore, we don't have to define that parameter here.
|
* enough that we just pass 'null' as the second argument, therefore, we don't have to define that parameter here.
|
||||||
@ -76,18 +64,31 @@ interface Gtk {
|
|||||||
boolean gtk_init_check(int argc);
|
boolean gtk_init_check(int argc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* Creates a new GMainLoop structure.
|
||||||
* innermost invocation of the main loop return.
|
|
||||||
*/
|
*/
|
||||||
void gtk_main();
|
GMainLoop g_main_loop_new(Pointer context, boolean is_running);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the innermost invocation of the main loop return when it regains control. ONLY CALL FROM THE GtkSupport class, UNLESS you know
|
* Runs a main loop until g_main_loop_quit() is called on the loop. If this is called for the thread of the loop's GMainContext,
|
||||||
* what you're doing!
|
* it will process events from the loop, otherwise it will simply wait.
|
||||||
*/
|
*/
|
||||||
void gtk_main_quit();
|
void g_main_loop_run(GMainLoop loop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops a GMainLoop from running. Any calls to g_main_loop_run() for the loop will return.
|
||||||
|
* Note that sources that have already been dispatched when g_main_loop_quit() is called will still be executed.
|
||||||
|
*/
|
||||||
|
void g_main_loop_quit(GMainLoop loop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the GMainContext of loop .
|
||||||
|
*/
|
||||||
|
GMainContext g_main_loop_get_context(GMainLoop loop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes a function in such a way that context is owned during the invocation of function .
|
||||||
|
*/
|
||||||
|
void g_main_context_invoke(GMainContext c, FuncCallback func, Pointer data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new GtkMenu
|
* Creates a new GtkMenu
|
||||||
|
@ -29,21 +29,29 @@ public
|
|||||||
class Gtk2 implements Gtk {
|
class Gtk2 implements Gtk {
|
||||||
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 | grep gtk
|
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 | grep gtk
|
||||||
|
|
||||||
@Override
|
|
||||||
public native
|
|
||||||
int gdk_threads_add_idle_full(final int priority, final FuncCallback function, final Pointer data, final Pointer notify);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native
|
public native
|
||||||
boolean gtk_init_check(final int argc);
|
boolean gtk_init_check(final int argc);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native
|
public native
|
||||||
void gtk_main();
|
GMainLoop g_main_loop_new(Pointer context, boolean is_running);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native
|
public native
|
||||||
void gtk_main_quit();
|
GMainContext g_main_loop_get_context(GMainLoop loop);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native
|
||||||
|
void g_main_loop_run(GMainLoop loop);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native
|
||||||
|
void g_main_context_invoke(GMainContext c, FuncCallback func, Pointer data);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native
|
||||||
|
void g_main_loop_quit(GMainLoop loop);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native
|
public native
|
||||||
|
@ -128,21 +128,29 @@ class Gtk3 implements Gtk {
|
|||||||
this.gtk_widget_get_preferred_size(widget, requisition, null);
|
this.gtk_widget_get_preferred_size(widget, requisition, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public native
|
|
||||||
int gdk_threads_add_idle_full(final int priority, final FuncCallback function, final Pointer data, final Pointer notify);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native
|
public native
|
||||||
boolean gtk_init_check(final int argc);
|
boolean gtk_init_check(final int argc);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native
|
public native
|
||||||
void gtk_main();
|
GMainLoop g_main_loop_new(Pointer context, boolean is_running);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native
|
public native
|
||||||
void gtk_main_quit();
|
GMainContext g_main_loop_get_context(GMainLoop loop);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native
|
||||||
|
void g_main_loop_run(GMainLoop loop);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native
|
||||||
|
void g_main_context_invoke(GMainContext c, FuncCallback func, Pointer data);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native
|
||||||
|
void g_main_loop_quit(GMainLoop loop);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native
|
public native
|
||||||
|
@ -52,6 +52,9 @@ class GtkEventDispatch {
|
|||||||
@SuppressWarnings("FieldCanBeLocal")
|
@SuppressWarnings("FieldCanBeLocal")
|
||||||
private static Thread gtkUpdateThread = null;
|
private static Thread gtkUpdateThread = null;
|
||||||
|
|
||||||
|
private static GMainLoop mainloop;
|
||||||
|
private static GMainContext context;
|
||||||
|
|
||||||
// when debugging the EDT, we need a longer timeout.
|
// when debugging the EDT, we need a longer timeout.
|
||||||
private static final boolean debugEDT = false;
|
private static final boolean debugEDT = false;
|
||||||
|
|
||||||
@ -72,7 +75,6 @@ class GtkEventDispatch {
|
|||||||
|
|
||||||
// startup the GTK GUI event loop. There can be multiple/nested loops.
|
// startup the GTK GUI event loop. There can be multiple/nested loops.
|
||||||
|
|
||||||
|
|
||||||
if (!GtkLoader.alreadyRunningGTK) {
|
if (!GtkLoader.alreadyRunningGTK) {
|
||||||
// If JavaFX/SWT is used, this is UNNECESSARY (we can detect if the GTK main_loop is running)
|
// If JavaFX/SWT is used, this is UNNECESSARY (we can detect if the GTK main_loop is running)
|
||||||
|
|
||||||
@ -91,24 +93,22 @@ class GtkEventDispatch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// prep for the event loop.
|
|
||||||
// GThread.g_thread_init(null); would be needed for g_idle_add()
|
|
||||||
|
|
||||||
if (!Gtk2.gtk_init_check(0)) {
|
if (!Gtk2.gtk_init_check(0)) {
|
||||||
throw new RuntimeException("Error starting GTK");
|
throw new RuntimeException("Error starting GTK");
|
||||||
}
|
}
|
||||||
|
|
||||||
// gdk_threads_enter(); would be needed for g_idle_add()
|
|
||||||
|
// create the main-loop
|
||||||
|
mainloop = Gtk2.g_main_loop_new(null, false);
|
||||||
|
context = Gtk2.g_main_loop_get_context(mainloop);
|
||||||
|
|
||||||
|
// blocks until we quit the main loop
|
||||||
|
Gtk2.g_main_loop_run(mainloop);
|
||||||
|
|
||||||
|
|
||||||
if (orig != null) {
|
if (orig != null) {
|
||||||
Glib.g_log_set_default_handler(orig, null);
|
Glib.g_log_set_default_handler(orig, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// blocks unit quit
|
|
||||||
Gtk2.gtk_main();
|
|
||||||
|
|
||||||
// clean up threads
|
|
||||||
// gdk_threads_leave(); would be needed for g_idle_add()
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
gtkUpdateThread.setDaemon(false); // explicitly NOT daemon so that this will hold the JVM open as necessary
|
gtkUpdateThread.setDaemon(false); // explicitly NOT daemon so that this will hold the JVM open as necessary
|
||||||
@ -302,10 +302,6 @@ class GtkEventDispatch {
|
|||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
int callback(final Pointer data) {
|
int callback(final Pointer data) {
|
||||||
synchronized (gtkCallbacks) {
|
|
||||||
gtkCallbacks.removeFirst(); // now that we've 'handled' it, we can remove it from our callback list
|
|
||||||
}
|
|
||||||
|
|
||||||
isDispatch.set(true);
|
isDispatch.set(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -314,6 +310,10 @@ class GtkEventDispatch {
|
|||||||
isDispatch.set(false);
|
isDispatch.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized (gtkCallbacks) {
|
||||||
|
gtkCallbacks.removeFirst(); // now that we've 'handled' it, we can remove it from our callback list
|
||||||
|
}
|
||||||
|
|
||||||
return Gtk2.FALSE; // don't want to call this again
|
return Gtk2.FALSE; // don't want to call this again
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -322,8 +322,8 @@ class GtkEventDispatch {
|
|||||||
gtkCallbacks.offer(callback); // prevent GC from collecting this object before it can be called
|
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
|
// explicitly invoke on our new GTK main loop context
|
||||||
Gtk2.gdk_threads_add_idle_full(100, callback, null, null);
|
Gtk2.g_main_context_invoke(context, callback, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -352,7 +352,8 @@ class GtkEventDispatch {
|
|||||||
void run() {
|
void run() {
|
||||||
// If JavaFX/SWT is used, this is UNNECESSARY (and will break SWT/JavaFX shutdown)
|
// If JavaFX/SWT is used, this is UNNECESSARY (and will break SWT/JavaFX shutdown)
|
||||||
if (!GtkLoader.alreadyRunningGTK) {
|
if (!GtkLoader.alreadyRunningGTK) {
|
||||||
Gtk2.gtk_main_quit();
|
Gtk2.g_main_loop_quit(mainloop);
|
||||||
|
// Gtk2.gtk_main_quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
started = false;
|
started = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user