Windows, Linux, JDK11.
JNA Linux, Linux, Gtk (Gimp Toolkit).
, Gtk, API Gtk, , . , ( HiDPI ), .
: Java - , Gtk API - , . , Linux: - ().
: GtkUtilities.getScaleFactor()
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.lang.reflect.Method;
public class GtkUtilities {
public static double getScaleFactor() {
GTK gtkHandle = getGtkInstance();
if (gtkHandle != null && gtkHandle.gtk_init_check(0, null)) {
System.out.println("Initialized Gtk");
if (gtkHandle instanceof GTK2) {
return getGtk2ScaleFactor((GTK2)gtkHandle);
} else {
return getGtk3ScaleFactor((GTK3)gtkHandle);
}
} else {
System.err.println("An error occurred initializing the Gtk library");
}
return 0;
}
private static GTK getGtkInstance() {
System.out.println("Finding preferred Gtk version...");
switch(getGtkMajorVersion()) {
case 2:
return GTK2.INSTANCE;
case 3:
return GTK3.INSTANCE;
default:
System.err.println("Not a compatible Gtk version");
}
return null;
}
private static int getGtkMajorVersion() {
try {
Class toolkitClass = Class.forName("sun.awt.UNIXToolkit");
Method versionMethod = toolkitClass.getDeclaredMethod("getGtkVersion");
Enum versionInfo = (Enum)versionMethod.invoke(toolkitClass);
Method numberMethod = versionInfo.getClass().getDeclaredMethod("getNumber");
int version = ((Integer)numberMethod.invoke(versionInfo)).intValue();
System.out.println("Found Gtk " + version);
return version;
} catch(Throwable t) {
System.err.println("Could not obtain GtkVersion information from UNIXToolkit: {}", t.getMessage());
}
return 0;
}
private static double getGtk2ScaleFactor(GTK2 gtk2) {
Pointer display = gtk2.gdk_display_get_default();
System.out.println("Gtk 2.10+ detected, calling \"gdk_screen_get_resolution\"");
Pointer screen = gtk2.gdk_display_get_default_screen(display);
return gtk2.gdk_screen_get_resolution(screen) / 96.0d;
}
private static double getGtk3ScaleFactor(GTK3 gtk3) {
Pointer display = gtk3.gdk_display_get_default();
int gtkMinorVersion = gtk3.gtk_get_minor_version();
if (gtkMinorVersion < 10) {
System.err.println("Gtk 3.10+ is required to detect scaling factor, skipping.");
} else if (gtkMinorVersion >= 22) {
System.out.println("Gtk 3.22+ detected, calling \"gdk_monitor_get_scale_factor\"");
Pointer monitor = gtk3.gdk_display_get_primary_monitor(display);
return gtk3.gdk_monitor_get_scale_factor(monitor);
} else if (gtkMinorVersion >= 10) {
System.out.println("Gtk 3.10+ detected, calling \"gdk_screen_get_monitor_scale_factor\"");
Pointer screen = gtk3.gdk_display_get_default_screen(display);
return gtk3.gdk_screen_get_monitor_scale_factor(screen, 0);
}
return 0;
}
private interface GTK extends Library {
boolean gtk_init_check(int argc, String[] argv);
Pointer gdk_display_get_default();
Pointer gdk_display_get_default_screen (Pointer display);
}
private interface GTK3 extends GTK {
GTK3 INSTANCE = Native.loadLibrary("gtk-3", GTK3.class);
int gtk_get_minor_version ();
int gdk_screen_get_monitor_scale_factor (Pointer screen, int monitor_num);
Pointer gdk_display_get_primary_monitor (Pointer display);
int gdk_monitor_get_scale_factor (Pointer monitor);
}
private interface GTK2 extends GTK {
GTK2 INSTANCE = Native.loadLibrary("gtk-x11-2.0", GTK2.class);
double gdk_screen_get_resolution(Pointer screen);
}
}