--- old/make/lib/Awt2dLibraries.gmk 2016-07-05 21:43:13.952555335 +0300 +++ new/make/lib/Awt2dLibraries.gmk 2016-07-05 21:43:13.776555331 +0300 @@ -931,7 +931,7 @@ LIBSPLASHSCREEN_LDFLAGS := -delayload:user32.dll LIBSPLASHSCREEN_LIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib $(WIN_JAVA_LIB) jvm.lib else - LIBSPLASHSCREEN_LIBS += $(X_LIBS) -lX11 -lXext $(LIBM) -lpthread + LIBSPLASHSCREEN_LIBS += $(X_LIBS) -lX11 -lXext $(LIBM) -lpthread -ldl endif $(eval $(call SetupNativeCompilation,BUILD_LIBSPLASHSCREEN, \ --- old/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2016-07-05 21:43:14.408555346 +0300 +++ new/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c 2016-07-05 21:43:14.276555343 +0300 @@ -2141,15 +2141,50 @@ * End DisplayMode/FullScreen support */ +static char *get_output_screen_name(JNIEnv *env, int screen) { + if (!awt_XRRGetScreenResources || !awt_XRRGetOutputInfo) { + return NULL; + } + char *name = NULL; + AWT_LOCK(); + int scr = 0, out = 0; + if (usingXinerama && XScreenCount(awt_display) > 0) { + out = screen; + } else { + scr = screen; + } + + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, + RootWindow(awt_display, scr)); + if (res) { + if (res->noutput > out) { + XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display, + res, res->outputs[out]); + if (output_info) { + if (output_info->name) { + name = strdup(output_info->name); + } + awt_XRRFreeOutputInfo(output_info); + } + } + awt_XRRFreeScreenResources(res); + } + AWT_UNLOCK(); + return name; +} /* * Class: sun_awt_X11GraphicsDevice * Method: getNativeScaleFactor - * Signature: (I)I + * Signature: (I)D */ -JNIEXPORT jint JNICALL +JNIEXPORT jdouble JNICALL Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor (JNIEnv *env, jobject this, jint screen) { - - return getNativeScaleFactor(); + char *name = get_output_screen_name(env, screen); + double scale = getNativeScaleFactor(name); + if (name) { + free(name); + } + return scale; } --- old/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c 2016-07-05 21:43:14.792555355 +0300 +++ new/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c 2016-07-05 21:43:14.664555352 +0300 @@ -22,23 +22,180 @@ */ #include "systemScale.h" +#include "jni.h" +#include "jni_util.h" +#include "jvm_md.h" +#include +#include #include +#include -int getNativeScaleFactor() { +typedef void* g_settings_schema_source_get_default(); +typedef void* g_settings_schema_source_ref(void *); +typedef void g_settings_schema_source_unref(void *); +typedef void* g_settings_schema_source_lookup(void *, char *, int); +typedef int g_settings_schema_has_key(void *, char *); +typedef void* g_settings_new_full(void *, void *, char *); +typedef void* g_settings_get_value(void *, char *); +typedef int g_variant_is_of_type(void *, char *); +typedef unsigned long g_variant_n_children(void *); +typedef void* g_variant_get_child_value(void *, unsigned long); +typedef void g_variant_unref(void *); +typedef char* g_variant_get_string(void *, unsigned long *); +typedef int g_variant_get_int32(void *); +typedef double g_variant_get_double(void *); + +static g_settings_schema_has_key* fp_g_settings_schema_has_key; +static g_settings_new_full* fp_g_settings_new_full; +static g_settings_get_value* fp_g_settings_get_value; +static g_variant_is_of_type* fp_g_variant_is_of_type; +static g_variant_n_children* fp_g_variant_n_children; +static g_variant_get_child_value* fp_g_variant_get_child_value; +static g_variant_get_string* fp_g_variant_get_string; +static g_variant_get_int32* fp_g_variant_get_int32; +static g_variant_get_double* fp_g_variant_get_double; +static g_variant_unref* fp_g_variant_unref; + +static void* get_schema_value(char *name, char *key) { + static void *lib_handle; + static int initialized = 0; + static void * default_schema; + static g_settings_schema_source_lookup* schema_lookup; + if (!initialized) { + initialized = 1; + void *lib_handle = dlopen(JNI_LIB_NAME("gio-2.0"), + RTLD_GLOBAL | RTLD_LAZY); + if (!lib_handle) { + lib_handle = dlopen(VERSIONED_JNI_LIB_NAME("gio-2.0", "0"), + RTLD_GLOBAL | RTLD_LAZY); + } + if (lib_handle == NULL) { + return NULL; + } + fp_g_settings_schema_has_key = + dlsym(lib_handle, "g_settings_schema_has_key"); + if (!fp_g_settings_schema_has_key) { + return NULL; + } + fp_g_settings_new_full = dlsym(lib_handle, "g_settings_new_full"); + if (!fp_g_settings_new_full) { + return NULL; + } + fp_g_settings_get_value = dlsym(lib_handle, "g_settings_get_value"); + if (!fp_g_settings_get_value) { + return NULL; + } + fp_g_variant_is_of_type = dlsym(lib_handle, "g_variant_is_of_type"); + if (!fp_g_variant_is_of_type) { + return NULL; + } + fp_g_variant_n_children = dlsym(lib_handle, "g_variant_n_children"); + if (!fp_g_variant_n_children) { + return NULL; + } + fp_g_variant_get_child_value = + dlsym(lib_handle, "g_variant_get_child_value"); + if (!fp_g_variant_get_child_value) { + return NULL; + } + fp_g_variant_get_string = dlsym(lib_handle, "g_variant_get_string"); + if (!fp_g_variant_get_string) { + return NULL; + } + fp_g_variant_get_int32 = dlsym(lib_handle, "g_variant_get_int32"); + if (!fp_g_variant_get_int32) { + return NULL; + } + fp_g_variant_get_double = dlsym(lib_handle, "g_variant_get_double"); + if (!fp_g_variant_get_double) { + return NULL; + } + fp_g_variant_unref = dlsym(lib_handle, "g_variant_unref"); + if (!fp_g_variant_unref) { + return NULL; + } - static int scale = -2.0; + void *fp = dlsym(lib_handle, "g_settings_schema_source_get_default"); + if (fp) { + default_schema = ((g_settings_schema_source_get_default*)fp)(); + } + if (default_schema) { + fp = dlsym(lib_handle, "g_settings_schema_source_ref"); + if (fp) { + ((g_settings_schema_source_ref*)fp)(default_schema); + } + } + schema_lookup = dlsym(lib_handle, "g_settings_schema_source_lookup"); + } - if (scale == -2) { - scale = getScale("J2D_UISCALE"); + if (!default_schema || !schema_lookup) { + return NULL; + } + void *schema = schema_lookup(default_schema, name, 1); + if (schema) { + if (fp_g_settings_schema_has_key(schema, key)) { + void *settings = fp_g_settings_new_full(schema, NULL, NULL); + if (settings) { + return fp_g_settings_get_value(settings, key); + } + } } + return NULL; +} - if (scale >= 1) { - return (int) scale; + +static double getDesktopScale(char *output_name) { + double result = -1; + if(output_name) { + void *value = get_schema_value("com.ubuntu.user-interface", + "scale-factor"); + if (value) { + if(fp_g_variant_is_of_type(value, "a{si}")) { + int num = fp_g_variant_n_children(value); + int i = 0; + while (i < num) { + void *entry = fp_g_variant_get_child_value(value, i++); + if (entry) { + void *screen = fp_g_variant_get_child_value(entry, 0); + void *scale = fp_g_variant_get_child_value(entry, 1); + if (screen && scale) { + char *name = fp_g_variant_get_string(screen, NULL); + if (name && strcmp(name, output_name)) { + result = fp_g_variant_get_int32(scale) / 8.; + } + fp_g_variant_unref(screen); + fp_g_variant_unref(scale); + } + fp_g_variant_unref(entry); + } + } + } + fp_g_variant_unref(value); + } + if (result > 0) { + value = get_schema_value("com.canonical.Unity.Interface", + "text-scale-factor"); + if (value && fp_g_variant_is_of_type(value, "d")) { + result *= fp_g_variant_get_double(value); + fp_g_variant_unref(value); + } + } + } + + if (result <= 0) { + void *value = get_schema_value("org.gnome.desktop.interface", + "text-scaling-factor"); + if (value && fp_g_variant_is_of_type(value, "d")) { + result = fp_g_variant_get_double(value); + fp_g_variant_unref(value); + } } - return getScale("GDK_SCALE"); + + return result; + } -int getScale(const char *name) { +static int getScale(const char *name) { char *uiScale = getenv(name); if (uiScale != NULL) { double scale = strtod(uiScale, NULL); @@ -50,3 +207,25 @@ return -1; } +double getNativeScaleFactor(char *output_name) { + + static int scale = -2.0; + + if (scale == -2) { + scale = getScale("J2D_UISCALE"); + } + + if (scale > 0) { + return scale; + } + + double native_scale = getDesktopScale(output_name); + + if (native_scale <= 0) { + native_scale = 1; + } + + int gdk_scale = getScale("GDK_SCALE"); + + return gdk_scale > 0 ? native_scale * gdk_scale : native_scale; +} --- old/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h 2016-07-05 21:43:15.172555364 +0300 +++ new/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h 2016-07-05 21:43:15.040555361 +0300 @@ -26,8 +26,7 @@ #include #include -int getNativeScaleFactor(); -int getScale(const char *uiScale); +double getNativeScaleFactor(); #endif --- old/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java 2016-07-05 21:43:15.472555371 +0300 +++ new/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java 2016-07-05 21:43:15.340555368 +0300 @@ -281,7 +281,7 @@ int width, int height, int displayMode); private static native void resetNativeData(int screen); - private static native int getNativeScaleFactor(int screen); + private static native double getNativeScaleFactor(int screen); /** * Returns true only if: @@ -516,6 +516,11 @@ return scale; } + public int getNativeScale() { + isXrandrExtensionSupported(); + return (int)Math.round(getNativeScaleFactor(screen)); + } + private int initScaleFactor() { if (SunGraphicsEnvironment.isUIScaleEnabled()) { @@ -525,8 +530,7 @@ if (debugScale >= 1) { return (int) debugScale; } - - int nativeScale = getNativeScaleFactor(screen); + int nativeScale = getNativeScale(); return nativeScale >= 1 ? nativeScale : 1; }