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
|
||||
|
||||
public static native void g_object_ref(Pointer object);
|
||||
public static native void g_object_unref(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;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* innermost invocation of the main loop return.
|
||||
* Creates a new GMainLoop structure.
|
||||
*/
|
||||
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
|
||||
* what you're doing!
|
||||
* 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,
|
||||
* 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
|
||||
|
@ -29,21 +29,29 @@ public
|
||||
class Gtk2 implements 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
|
||||
public native
|
||||
boolean gtk_init_check(final int argc);
|
||||
|
||||
@Override
|
||||
public native
|
||||
void gtk_main();
|
||||
GMainLoop g_main_loop_new(Pointer context, boolean is_running);
|
||||
|
||||
@Override
|
||||
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
|
||||
public native
|
||||
|
@ -128,21 +128,29 @@ class Gtk3 implements Gtk {
|
||||
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
|
||||
public native
|
||||
boolean gtk_init_check(final int argc);
|
||||
|
||||
@Override
|
||||
public native
|
||||
void gtk_main();
|
||||
GMainLoop g_main_loop_new(Pointer context, boolean is_running);
|
||||
|
||||
@Override
|
||||
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
|
||||
public native
|
||||
|
@ -52,6 +52,9 @@ class GtkEventDispatch {
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private static Thread gtkUpdateThread = null;
|
||||
|
||||
private static GMainLoop mainloop;
|
||||
private static GMainContext context;
|
||||
|
||||
// when debugging the EDT, we need a longer timeout.
|
||||
private static final boolean debugEDT = false;
|
||||
|
||||
@ -72,7 +75,6 @@ class GtkEventDispatch {
|
||||
|
||||
// startup the GTK GUI event loop. There can be multiple/nested loops.
|
||||
|
||||
|
||||
if (!GtkLoader.alreadyRunningGTK) {
|
||||
// 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)) {
|
||||
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) {
|
||||
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
|
||||
@ -302,10 +302,6 @@ class GtkEventDispatch {
|
||||
@Override
|
||||
public
|
||||
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);
|
||||
|
||||
try {
|
||||
@ -314,6 +310,10 @@ class GtkEventDispatch {
|
||||
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
|
||||
}
|
||||
};
|
||||
@ -322,8 +322,8 @@ class GtkEventDispatch {
|
||||
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
|
||||
Gtk2.gdk_threads_add_idle_full(100, callback, null, null);
|
||||
// explicitly invoke on our new GTK main loop context
|
||||
Gtk2.g_main_context_invoke(context, callback, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -352,7 +352,8 @@ class GtkEventDispatch {
|
||||
void run() {
|
||||
// If JavaFX/SWT is used, this is UNNECESSARY (and will break SWT/JavaFX shutdown)
|
||||
if (!GtkLoader.alreadyRunningGTK) {
|
||||
Gtk2.gtk_main_quit();
|
||||
Gtk2.g_main_loop_quit(mainloop);
|
||||
// Gtk2.gtk_main_quit();
|
||||
}
|
||||
|
||||
started = false;
|
||||
|
Loading…
Reference in New Issue
Block a user