# HG changeset patch # User ssadetsky # Date 1467992592 -10800 # Node ID a3cc7e551a48c057b0d52d9b1d96a200b6f99007 # Parent 6f69de78d0ebd216fcdf22070228f15264813c84 8149115: [hidpi] Linux: display-wise scaling factor should probably be taken into account Reviewed-by: alexsch, azvegint diff -r 6f69de78d0eb -r a3cc7e551a48 jdk/make/lib/Awt2dLibraries.gmk --- a/jdk/make/lib/Awt2dLibraries.gmk Fri Jul 08 19:32:52 2016 +0530 +++ b/jdk/make/lib/Awt2dLibraries.gmk Fri Jul 08 18:43:12 2016 +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, \ diff -r 6f69de78d0eb -r a3cc7e551a48 jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java Fri Jul 08 19:32:52 2016 +0530 +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java Fri Jul 08 18:43:12 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -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; } diff -r 6f69de78d0eb -r a3cc7e551a48 jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c --- a/jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c Fri Jul 08 19:32:52 2016 +0530 +++ b/jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c Fri Jul 08 18:43:12 2016 +0300 @@ -22,23 +22,171 @@ */ #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 int scale = -2.0; +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; + void *schema = NULL, *fp = NULL; + if (!initialized) { + initialized = 1; + lib_handle = dlopen(JNI_LIB_NAME("gio-2.0"), RTLD_GLOBAL | RTLD_LAZY); + if (!lib_handle) { + CHECK_NULL_RETURN(lib_handle = + dlopen(VERSIONED_JNI_LIB_NAME("gio-2.0", "0"), + RTLD_GLOBAL | RTLD_LAZY), NULL); + } + CHECK_NULL_RETURN(fp_g_settings_schema_has_key = + (g_settings_schema_has_key*) + dlsym(lib_handle, "g_settings_schema_has_key"), NULL); + CHECK_NULL_RETURN(fp_g_settings_new_full = + (g_settings_new_full*) + dlsym(lib_handle, "g_settings_new_full"), NULL); + CHECK_NULL_RETURN(fp_g_settings_get_value = + (g_settings_get_value*) + dlsym(lib_handle, "g_settings_get_value"), NULL); + CHECK_NULL_RETURN(fp_g_variant_is_of_type = + (g_variant_is_of_type*) + dlsym(lib_handle, "g_variant_is_of_type"), NULL); + CHECK_NULL_RETURN(fp_g_variant_n_children = + (g_variant_n_children*) + dlsym(lib_handle, "g_variant_n_children"), NULL); + CHECK_NULL_RETURN(fp_g_variant_get_child_value = + (g_variant_get_child_value*) + dlsym(lib_handle, "g_variant_get_child_value"), NULL); + CHECK_NULL_RETURN(fp_g_variant_get_string = + (g_variant_get_string*) + dlsym(lib_handle, "g_variant_get_string"), NULL); + CHECK_NULL_RETURN(fp_g_variant_get_int32 = + (g_variant_get_int32*) + dlsym(lib_handle, "g_variant_get_int32"), NULL); + CHECK_NULL_RETURN(fp_g_variant_get_double = + (g_variant_get_double*) + dlsym(lib_handle, "g_variant_get_double"), NULL); + CHECK_NULL_RETURN(fp_g_variant_unref = + (g_variant_unref*) + dlsym(lib_handle, "g_variant_unref"), NULL); - if (scale == -2) { - scale = getScale("J2D_UISCALE"); + 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 = (g_settings_schema_source_lookup*) + dlsym(lib_handle, "g_settings_schema_source_lookup"); } - if (scale >= 1) { - return (int) scale; + if (!default_schema || !schema_lookup) { + return NULL; } - return getScale("GDK_SCALE"); + + 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; } -int getScale(const char *name) { + +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); + } + if (result > 0) { + break; + } + } + } + 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 result; + +} + +static int getScale(const char *name) { char *uiScale = getenv(name); if (uiScale != NULL) { double scale = strtod(uiScale, NULL); @@ -50,3 +198,26 @@ return -1; } +double getNativeScaleFactor(char *output_name) { + static int scale = -2.0; + double native_scale = 0; + int gdk_scale = 0; + + if (scale == -2) { + scale = getScale("J2D_UISCALE"); + } + + if (scale > 0) { + return scale; + } + + native_scale = getDesktopScale(output_name); + + if (native_scale <= 0) { + native_scale = 1; + } + + gdk_scale = getScale("GDK_SCALE"); + + return gdk_scale > 0 ? native_scale * gdk_scale : native_scale; +} diff -r 6f69de78d0eb -r a3cc7e551a48 jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h --- a/jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h Fri Jul 08 19:32:52 2016 +0530 +++ b/jdk/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h Fri Jul 08 18:43:12 2016 +0300 @@ -26,8 +26,7 @@ #include #include -int getNativeScaleFactor(); -int getScale(const char *uiScale); +double getNativeScaleFactor(); #endif diff -r 6f69de78d0eb -r a3cc7e551a48 jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c --- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Fri Jul 08 19:32:52 2016 +0530 +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Fri Jul 08 18:43:12 2016 +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; }