Now support GTK3 versions less than 3.10 (3.4 was tested, as released on
Ubuntu 12.04). Make sure not to touch Gtk interface while loading Gtk
This commit is contained in:
parent
bb15ca12a8
commit
a5d7a7293e
@ -25,7 +25,7 @@ import dorkbox.util.jna.linux.structs.GtkStyle;
|
||||
* <p>
|
||||
* Direct-mapping, See: https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md
|
||||
*/
|
||||
@SuppressWarnings({"Duplicates", "SameParameterValue", "DeprecatedIsStillUsed", "WeakerAccess"})
|
||||
@SuppressWarnings({"Duplicates", "SameParameterValue", "DeprecatedIsStillUsed", "WeakerAccess", "UnusedReturnValue"})
|
||||
public
|
||||
interface Gtk {
|
||||
// objdump -T /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 | grep gtk
|
||||
@ -35,6 +35,12 @@ interface Gtk {
|
||||
// For funsies to look at, SyncThing did a LOT of work on compatibility in python (unfortunate for us, but interesting).
|
||||
// https://github.com/syncthing/syncthing-gtk/blob/b7a3bc00e3bb6d62365ae62b5395370f3dcc7f55/syncthing_gtk/statusicon.py
|
||||
|
||||
int FALSE = 0;
|
||||
int TRUE = 1;
|
||||
|
||||
int MAJOR = GtkLoader.MAJOR;
|
||||
int MINOR = GtkLoader.MINOR;
|
||||
int MICRO = GtkLoader.MICRO;
|
||||
|
||||
// make specific versions of GTK2 vs GTK3 APIs
|
||||
// ALSO, GTK must be loaded via .init()
|
||||
@ -49,12 +55,7 @@ interface Gtk {
|
||||
|
||||
Function gtk_status_icon_position_menu = GtkLoader.gtk_status_icon_position_menu;
|
||||
|
||||
int FALSE = 0;
|
||||
int TRUE = 1;
|
||||
|
||||
int MAJOR = GtkLoader.MAJOR;
|
||||
int MINOR = GtkLoader.MINOR;
|
||||
int MICRO = GtkLoader.MICRO;
|
||||
|
||||
/**
|
||||
* Adds a function to be called whenever there are no higher priority events pending. If the function returns FALSE it is automatically
|
||||
@ -78,11 +79,6 @@ interface Gtk {
|
||||
*/
|
||||
void gtk_main();
|
||||
|
||||
/**
|
||||
* aks for the current nesting level of the main loop. Useful to determine (at startup) if GTK is already running
|
||||
*/
|
||||
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
|
||||
* what you're doing!
|
||||
|
@ -41,10 +41,6 @@ class Gtk2 implements Gtk {
|
||||
public native
|
||||
void gtk_main();
|
||||
|
||||
@Override
|
||||
public native
|
||||
int gtk_main_level();
|
||||
|
||||
@Override
|
||||
public native
|
||||
void gtk_main_quit();
|
||||
|
@ -27,24 +27,19 @@ import dorkbox.util.jna.linux.structs.GtkStyle;
|
||||
*/
|
||||
public
|
||||
class Gtk3 implements Gtk {
|
||||
static Function gdk_window_get_scale_factor = 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
|
||||
|
||||
/**
|
||||
* This function is typically used when implementing a GtkContainer subclass. Obtains the preferred size of a widget. The
|
||||
* container uses this information to arrange its child widgets and decide what size allocations to give them with
|
||||
* gtk_widget_size_allocate().
|
||||
*
|
||||
* You can also call this function from an application, with some caveats. Most notably, getting a size request requires the
|
||||
* widget to be associated with a screen, because font information may be needed. Multihead-aware applications should keep this in mind.
|
||||
*
|
||||
* Also remember that the size request is not necessarily the size a widget will actually be allocated.
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
void gtk_widget_size_request(final Pointer widget, final Pointer requisition) {
|
||||
this.gtk_widget_get_preferred_size(widget, requisition, null);
|
||||
}
|
||||
public native
|
||||
int gtk_get_major_version();
|
||||
|
||||
public native
|
||||
int gtk_get_minor_version();
|
||||
|
||||
public native
|
||||
int gtk_get_micro_version();
|
||||
|
||||
/**
|
||||
* Retrieves the minimum and natural size of a widget, taking into account the widget’s preference for height-for-width management.
|
||||
@ -64,15 +59,6 @@ class Gtk3 implements Gtk {
|
||||
public native
|
||||
void gtk_widget_get_preferred_size(final Pointer widget, final Pointer minimum_size, final Pointer natural_size);
|
||||
|
||||
public native
|
||||
int gtk_get_major_version();
|
||||
|
||||
public native
|
||||
int gtk_get_minor_version();
|
||||
|
||||
public native
|
||||
int gtk_get_micro_version();
|
||||
|
||||
/**
|
||||
* Returns the internal scale factor that maps from window coordinates to the actual device pixels. On traditional systems this is 1,
|
||||
* but on very high density outputs this can be a higher value (often 2).
|
||||
@ -87,11 +73,34 @@ class Gtk3 implements Gtk {
|
||||
*
|
||||
* @since 3.10
|
||||
*/
|
||||
public native
|
||||
int gdk_window_get_scale_factor(Pointer window);
|
||||
|
||||
public
|
||||
int gdk_window_get_scale_factor(Pointer window) {
|
||||
if (gdk_window_get_scale_factor != null) {
|
||||
return gdk_window_get_scale_factor.invokeInt(new Object[]{window});
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
//// GTK2 methods
|
||||
///////////////////////////
|
||||
|
||||
/**
|
||||
* This function is typically used when implementing a GtkContainer subclass. Obtains the preferred size of a widget. The
|
||||
* container uses this information to arrange its child widgets and decide what size allocations to give them with
|
||||
* gtk_widget_size_allocate().
|
||||
*
|
||||
* You can also call this function from an application, with some caveats. Most notably, getting a size request requires the
|
||||
* widget to be associated with a screen, because font information may be needed. Multihead-aware applications should keep this in mind.
|
||||
*
|
||||
* Also remember that the size request is not necessarily the size a widget will actually be allocated.
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
void gtk_widget_size_request(final Pointer widget, final Pointer requisition) {
|
||||
this.gtk_widget_get_preferred_size(widget, requisition, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public native
|
||||
@ -105,10 +114,6 @@ class Gtk3 implements Gtk {
|
||||
public native
|
||||
void gtk_main();
|
||||
|
||||
@Override
|
||||
public native
|
||||
int gtk_main_level();
|
||||
|
||||
@Override
|
||||
public native
|
||||
void gtk_main_quit();
|
||||
|
36
src/dorkbox/util/jna/linux/Gtk3VersionInfo.java
Normal file
36
src/dorkbox/util/jna/linux/Gtk3VersionInfo.java
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* bindings for GTK+ 3 version info.
|
||||
* <p>
|
||||
* Direct-mapping, See: https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md
|
||||
*/
|
||||
public
|
||||
class Gtk3VersionInfo {
|
||||
// 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
|
||||
|
||||
public native
|
||||
int gtk_get_major_version();
|
||||
|
||||
public native
|
||||
int gtk_get_minor_version();
|
||||
|
||||
public native
|
||||
int gtk_get_micro_version();
|
||||
}
|
@ -81,6 +81,7 @@ class GtkEventDispatch {
|
||||
void run() {
|
||||
Glib.GLogFunc orig = null;
|
||||
if (DEBUG) {
|
||||
// don't suppress GTK warnings in debug mode
|
||||
LoggerFactory.getLogger(GtkEventDispatch.class).debug("Running GTK Native Event Loop");
|
||||
} else {
|
||||
// NOTE: This can output warnings, so we suppress them
|
||||
|
@ -15,8 +15,6 @@
|
||||
*/
|
||||
package dorkbox.util.jna.linux;
|
||||
|
||||
import static dorkbox.util.jna.linux.Gtk.Gtk2;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.sun.jna.Function;
|
||||
@ -84,23 +82,23 @@ class GtkLoader {
|
||||
String gtk2LibName = "gtk-x11-2.0";
|
||||
String gtk3LibName = "libgtk-3.so.0";
|
||||
|
||||
|
||||
if (!_isLoaded && shouldUseGtk2) {
|
||||
try {
|
||||
NativeLibrary library = JnaHelper.register(gtk2LibName, Gtk2.class);
|
||||
gtk_status_icon_position_menu = Function.getFunction(gtk2LibName, "gtk_status_icon_position_menu");
|
||||
_isGtk2 = true;
|
||||
Gtk gtk = new Gtk2();
|
||||
|
||||
// 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 started GTK -- so we DO NOT NEED TO.
|
||||
_alreadyRunningGTK = gtk.gtk_main_level() != 0;
|
||||
_isLoaded = true;
|
||||
_isGtk2 = true;
|
||||
|
||||
major = library.getGlobalVariableAddress("gtk_major_version").getInt(0);
|
||||
minor = library.getGlobalVariableAddress("gtk_minor_version").getInt(0);
|
||||
micro = library.getGlobalVariableAddress("gtk_micro_version").getInt(0);
|
||||
|
||||
gtk_status_icon_position_menu = library.getFunction( "gtk_status_icon_position_menu");
|
||||
Function gtk_main_level = library.getFunction("gtk_main_level");
|
||||
|
||||
// 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 started GTK -- so we DO NOT NEED TO.
|
||||
_alreadyRunningGTK = gtk_main_level.invokeInt(null) != 0;
|
||||
_isLoaded = true;
|
||||
if (GtkEventDispatch.DEBUG) {
|
||||
LoggerFactory.getLogger(GtkLoader.class).debug("GTK: {}", gtk2LibName);
|
||||
}
|
||||
@ -116,26 +114,35 @@ class GtkLoader {
|
||||
// start with version 3
|
||||
if (!_isLoaded) {
|
||||
try {
|
||||
// ALSO map Gtk2.java to GTK3 library.
|
||||
JnaHelper.register(gtk3LibName, Gtk3.class);
|
||||
gtk_status_icon_position_menu = Function.getFunction(gtk3LibName, "gtk_status_icon_position_menu");
|
||||
Gtk3 gtk = new Gtk3();
|
||||
// have to get the version information FIRST, because there are some really old GTK3 libraries out there.
|
||||
NativeLibrary library = JnaHelper.register(gtk3LibName, Gtk3VersionInfo.class);
|
||||
|
||||
Gtk3VersionInfo version = new Gtk3VersionInfo();
|
||||
major = version.gtk_get_major_version();
|
||||
minor = version.gtk_get_minor_version();
|
||||
micro = version.gtk_get_micro_version();
|
||||
library.dispose();
|
||||
|
||||
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");
|
||||
|
||||
// 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 started GTK -- so we DO NOT NEED TO.
|
||||
_alreadyRunningGTK = gtk.gtk_main_level() != 0;
|
||||
_alreadyRunningGTK = gtk_main_level.invokeInt(null) != 0;
|
||||
_isLoaded = true;
|
||||
|
||||
major = gtk.gtk_get_major_version();
|
||||
minor = gtk.gtk_get_minor_version();
|
||||
micro = gtk.gtk_get_micro_version();
|
||||
|
||||
if (GtkEventDispatch.DEBUG) {
|
||||
LoggerFactory.getLogger(GtkLoader.class).debug("GTK: {}", gtk3LibName);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
if (GtkEventDispatch.DEBUG) {
|
||||
LoggerFactory.getLogger(GtkLoader.class).error("Error loading library", e);
|
||||
LoggerFactory.getLogger(GtkLoader.class).error("Error loading library.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -144,18 +151,19 @@ class GtkLoader {
|
||||
if (!_isLoaded) {
|
||||
try {
|
||||
NativeLibrary library = JnaHelper.register(gtk2LibName, Gtk2.class);
|
||||
gtk_status_icon_position_menu = Function.getFunction(gtk2LibName, "gtk_status_icon_position_menu");
|
||||
|
||||
_isGtk2 = true;
|
||||
|
||||
// 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 started GTK -- so we DO NOT NEED TO.
|
||||
_alreadyRunningGTK = Gtk2.gtk_main_level() != 0;
|
||||
_isLoaded = true;
|
||||
|
||||
major = library.getGlobalVariableAddress("gtk_major_version").getInt(0);
|
||||
minor = library.getGlobalVariableAddress("gtk_minor_version").getInt(0);
|
||||
micro = library.getGlobalVariableAddress("gtk_micro_version").getInt(0);
|
||||
|
||||
gtk_status_icon_position_menu = Function.getFunction(gtk2LibName, "gtk_status_icon_position_menu");
|
||||
Function gtk_main_level = library.getFunction("gtk_main_level");
|
||||
|
||||
// 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 started GTK -- so we DO NOT NEED TO.
|
||||
_alreadyRunningGTK = gtk_main_level.invokeInt(null) != 0;
|
||||
_isLoaded = true;
|
||||
if (GtkEventDispatch.DEBUG) {
|
||||
LoggerFactory.getLogger(GtkLoader.class).debug("GTK: {}", gtk2LibName);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user