diff --git a/src/dorkbox/util/jna/linux/Gtk.java b/src/dorkbox/util/jna/linux/Gtk.java index 996152d..d8a89aa 100644 --- a/src/dorkbox/util/jna/linux/Gtk.java +++ b/src/dorkbox/util/jna/linux/Gtk.java @@ -38,6 +38,7 @@ interface Gtk { int FALSE = 0; int TRUE = 1; + // use GtkCheck for a safe accessor of these int MAJOR = GtkLoader.MAJOR; int MINOR = GtkLoader.MINOR; int MICRO = GtkLoader.MICRO; @@ -47,6 +48,7 @@ interface Gtk { Gtk Gtk2 = GtkLoader.isGtk2 ? new Gtk2() : new Gtk3(); Gtk3 Gtk3 = GtkLoader.isGtk2 ? null : (Gtk3) Gtk2; + // use GtkCheck for a safe accessor of these boolean isGtk2 = GtkLoader.isGtk2; boolean isGtk3 = GtkLoader.isGtk3; boolean isLoaded = GtkLoader.isLoaded; @@ -393,5 +395,12 @@ interface Gtk { * @since 2.12 */ void gtk_widget_set_tooltip_text(Pointer widget, String text); + + /** + * Gets the default GdkDisplay. This is a convenience function for gdk_display_manager_get_default_display (gdk_display_manager_get()). + * + * @since: 2.2 + */ + Pointer gdk_display_get_default(); } diff --git a/src/dorkbox/util/jna/linux/Gtk2.java b/src/dorkbox/util/jna/linux/Gtk2.java index 4d982f6..766975c 100644 --- a/src/dorkbox/util/jna/linux/Gtk2.java +++ b/src/dorkbox/util/jna/linux/Gtk2.java @@ -198,4 +198,8 @@ class Gtk2 implements Gtk { @Override public native void gtk_widget_set_tooltip_text(final Pointer widget, final String text); + + @Override + public native + Pointer gdk_display_get_default(); } diff --git a/src/dorkbox/util/jna/linux/Gtk3.java b/src/dorkbox/util/jna/linux/Gtk3.java index 06a46ca..60d56dc 100644 --- a/src/dorkbox/util/jna/linux/Gtk3.java +++ b/src/dorkbox/util/jna/linux/Gtk3.java @@ -16,6 +16,7 @@ package dorkbox.util.jna.linux; import com.sun.jna.Function; +import com.sun.jna.NativeLibrary; import com.sun.jna.Pointer; import dorkbox.util.jna.linux.structs.GtkStyle; @@ -25,13 +26,33 @@ import dorkbox.util.jna.linux.structs.GtkStyle; *

* Direct-mapping, See: https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md */ +@SuppressWarnings("WeakerAccess") public class Gtk3 implements Gtk { - static Function gdk_window_get_scale_factor = null; + private static Function gdk_window_get_scale_factor = null; + private static Function gtk_show_uri_on_window = null; // objdump -T /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 | grep gtk // objdump -T /usr/local/lib/libgtk-3.so.0 | grep gtk + /** + * Loads version specific methods + * + * @param library + */ + static + void loadMethods(final NativeLibrary library) { + // Abusing static fields this way is not proper, but it gets the job done nicely. + + if (GtkCheck.gtkIsGreaterOrEqual(3, 10, 0)) { + gdk_window_get_scale_factor = library.getFunction("gdk_window_get_scale_factor"); + } + + if (GtkCheck.gtkIsGreaterOrEqual(3, 22, 0)) { + gtk_show_uri_on_window = library.getFunction("gtk_show_uri_on_window"); + } + } + /** * Retrieves the minimum and natural size of a widget, taking into account the widget’s preference for height-for-width management. *

@@ -73,6 +94,22 @@ class Gtk3 implements Gtk { } } + /** + * @return TRUE on success, FALSE on error + * + * @since: 3.22 + */ + public + boolean gtk_show_uri_on_window(final Pointer parent, final String uri, final int timestamp, final Pointer error) { + if (gtk_show_uri_on_window != null) { + return (Boolean) gtk_show_uri_on_window.invoke(Boolean.class, new Object[] {parent, uri, timestamp, error}); + } + else { + return false; + } + } + + /////////////////////////// //// GTK2 methods /////////////////////////// @@ -258,4 +295,8 @@ class Gtk3 implements Gtk { @Override public native void gtk_widget_set_tooltip_text(final Pointer widget, final String text); + + @Override + public native + Pointer gdk_display_get_default(); } diff --git a/src/dorkbox/util/jna/linux/GtkCheck.java b/src/dorkbox/util/jna/linux/GtkCheck.java index bfbe4ad..458e04f 100644 --- a/src/dorkbox/util/jna/linux/GtkCheck.java +++ b/src/dorkbox/util/jna/linux/GtkCheck.java @@ -45,6 +45,47 @@ class GtkCheck { */ public static volatile boolean isGtkLoaded = false; + + /** If GTK is loaded, this is the GTK MAJOR version */ + public static volatile int MAJOR = 0; + + /** If GTK is loaded, this is the GTK MINOR version */ + public static volatile int MINOR = 0; + + /** If GTK is loaded, this is the GTK MICRO version */ + public static volatile int MICRO = 0; + + + /** + * @return true if the currently loaded GTK version is greater to or equal to the passed-in major.minor.mico + */ + public static + boolean gtkIsGreaterOrEqual(final int major, final int minor, final int micro) { + if (MAJOR > major) { + return true; + } + if (MAJOR < major) { + return false; + } + + if (MINOR > minor) { + return true; + } + if (MINOR < minor) { + return false; + } + + if (MICRO > micro) { + return true; + } + if (MICRO < micro) { + return false; + } + + // same exact version + return true; + } + /** * This method is agnostic w.r.t. how GTK is loaded, which can be manually loaded or loaded via JavaFX/SWT/Swing. * @@ -80,4 +121,6 @@ class GtkCheck { // now check if swing has loaded GTK from the Look and Feel return SwingUtil.getLoadedGtkVersion(); } + + } diff --git a/src/dorkbox/util/jna/linux/GtkLoader.java b/src/dorkbox/util/jna/linux/GtkLoader.java index 0dd7aa5..15f8418 100644 --- a/src/dorkbox/util/jna/linux/GtkLoader.java +++ b/src/dorkbox/util/jna/linux/GtkLoader.java @@ -49,6 +49,7 @@ class GtkLoader { static Function gtk_status_icon_position_menu = null; + // use GtkCheck for a safe accessor of these static int MAJOR; static int MINOR; static int MICRO; @@ -139,10 +140,6 @@ class GtkLoader { library = null; library = JnaHelper.register(gtk3LibName, Gtk3.class); - if (major >= 3 && minor >= 10) { - // Abusing static fields this way is not proper, but it gets the job done nicely. - Gtk3.gdk_window_get_scale_factor = library.getFunction("gdk_window_get_scale_factor"); - } gtk_status_icon_position_menu = library.getFunction( "gtk_status_icon_position_menu"); Function gtk_main_level = library.getFunction("gtk_main_level"); @@ -229,6 +226,16 @@ class GtkLoader { GtkCheck.isGtk3 = isGtk3; GtkCheck.isGtkLoaded = isLoaded; + GtkCheck.MAJOR = MAJOR; + GtkCheck.MINOR = MINOR; + GtkCheck.MICRO = MICRO; + + + // load any GTK version specific methods + if (isGtk3) { + Gtk3.loadMethods(library); + } + if (shouldLoadGtk) { if (!_isLoaded) { throw new RuntimeException("We apologize for this, but we are unable to determine the GTK library is in use, " +