From 0f0027c4c697697c13d6be44210a000a5bfec00a Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Thu, 18 Mar 2021 13:26:35 +0300 Subject: [PATCH] Revert "8239894: Xserver crashes when the wrong high refresh rate is used" This code is needed for "Read org.gnome.desktop.interface/scaling-factor". Keep it until "JDK-8260270 Implement the HiDPI scale factor reading" is fixed. This reverts commit a7c2ebc7 (cherry picked from commit a249b989e1851b94458e6aad33d7713bb3ad6522) --- .../classes/sun/awt/X11GraphicsDevice.java | 5 +- .../common/awt/systemscale/systemScale.c | 178 +++++++++++++++++- .../common/awt/systemscale/systemScale.h | 4 +- .../native/libawt_xawt/awt/awt_GraphicsEnv.c | 130 ++++++++++++- .../native/libsplashscreen/splashscreen_sys.c | 2 +- 5 files changed, 304 insertions(+), 15 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index eed50962f0d6..ed84a8a41d44 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -415,10 +415,7 @@ public final class X11GraphicsDevice extends GraphicsDevice @Override public synchronized DisplayMode[] getDisplayModes() { - if (!isFullScreenSupported() - || ((X11GraphicsEnvironment) GraphicsEnvironment - .getLocalGraphicsEnvironment()).runningXinerama()) { - // only the current mode will be returned + if (!isFullScreenSupported()) { return super.getDisplayModes(); } ArrayList modes = new ArrayList(); diff --git a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c index cb14db56a919..d0a9f5c4c078 100644 --- a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c +++ b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -24,7 +24,169 @@ */ #include "systemScale.h" +#include "jni.h" +#include "jni_util.h" +#include "jvm_md.h" +#include +#include #include +#include + +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; + 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); + + 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 (!default_schema || !schema_lookup) { + return NULL; + } + + 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; +} + + +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); @@ -38,8 +200,10 @@ static int getScale(const char *name) { return -1; } -double getNativeScaleFactor() { +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"); @@ -49,5 +213,13 @@ double getNativeScaleFactor() { return scale; } - return getScale("GDK_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 --git a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h index 2dc6e37c3a3d..10de165f4138 100644 --- a/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h +++ b/src/java.desktop/unix/native/common/awt/systemscale/systemScale.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -28,7 +28,7 @@ #include #include -double getNativeScaleFactor(); +double getNativeScaleFactor(char *output_name); #endif diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index 51c425c8c593..119e404ba13f 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -1738,7 +1738,49 @@ Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode AWT_LOCK(); - if (screen < ScreenCount(awt_display)) { + if (usingXinerama && XScreenCount(awt_display) > 0) { + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, + RootWindow(awt_display, 0)); + if (res) { + if (res->noutput > screen) { + XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display, + res, res->outputs[screen]); + if (output_info) { + if (output_info->crtc) { + XRRCrtcInfo *crtc_info = + awt_XRRGetCrtcInfo (awt_display, res, + output_info->crtc); + if (crtc_info) { + if (crtc_info->mode) { + int i; + for (i = 0; i < res->nmode; i++) { + XRRModeInfo *mode = &res->modes[i]; + if (mode->id == crtc_info->mode) { + float rate = 0; + if (mode->hTotal && mode->vTotal) { + rate = ((float)mode->dotClock / + ((float)mode->hTotal * + (float)mode->vTotal)); + } + displayMode = X11GD_CreateDisplayMode( + env, + mode->width, + mode->height, + BIT_DEPTH_MULTI, + (int)(rate +.2)); + break; + } + } + } + awt_XRRFreeCrtcInfo(crtc_info); + } + } + awt_XRRFreeOutputInfo(output_info); + } + } + awt_XRRFreeScreenResources(res); + } + } else { config = awt_XRRGetScreenInfo(awt_display, RootWindow(awt_display, screen)); @@ -1788,8 +1830,45 @@ Java_sun_awt_X11GraphicsDevice_enumDisplayModes AWT_LOCK(); - if (XScreenCount(awt_display) > 0) { - + if (usingXinerama && XScreenCount(awt_display) > 0) { + XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, + RootWindow(awt_display, 0)); + if (res) { + if (res->noutput > screen) { + XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display, + res, res->outputs[screen]); + if (output_info) { + int i; + for (i = 0; i < output_info->nmode; i++) { + RRMode m = output_info->modes[i]; + int j; + XRRModeInfo *mode; + for (j = 0; j < res->nmode; j++) { + mode = &res->modes[j]; + if (mode->id == m) { + float rate = 0; + if (mode->hTotal && mode->vTotal) { + rate = ((float)mode->dotClock / + ((float)mode->hTotal * + (float)mode->vTotal)); + } + X11GD_AddDisplayMode(env, arrayList, + mode->width, mode->height, + BIT_DEPTH_MULTI, (int)(rate +.2)); + if ((*env)->ExceptionCheck(env)) { + goto ret0; + } + break; + } + } + } +ret0: + awt_XRRFreeOutputInfo(output_info); + } + } + awt_XRRFreeScreenResources(res); + } + } else { XRRScreenConfiguration *config; config = awt_XRRGetScreenInfo(awt_display, @@ -1947,6 +2026,42 @@ Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive * End DisplayMode/FullScreen support */ +static char *get_output_screen_name(JNIEnv *env, int screen) { +#ifdef NO_XRANDR + return NULL; +#else + 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; +#endif /* NO_XRANDR */ +} + /* * Class: sun_awt_X11GraphicsDevice * Method: getNativeScaleFactor @@ -1955,6 +2070,11 @@ Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive JNIEXPORT jdouble JNICALL Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor (JNIEnv *env, jobject this, jint screen) { - - return getNativeScaleFactor(); + // in case of Xinerama individual screen scales are not supported + char *name = get_output_screen_name(env, usingXinerama ? 0 : screen); + double scale = getNativeScaleFactor(name); + if (name) { + free(name); + } + return scale; } diff --git a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c index e89d813fff46..2e1e10fcecfe 100644 --- a/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c +++ b/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c @@ -782,7 +782,7 @@ SplashGetScaledImageName(const char* jarName, const char* fileName, #ifndef __linux__ return JNI_FALSE; #endif - *scaleFactor = (float)getNativeScaleFactor(); + *scaleFactor = (float)getNativeScaleFactor(NULL); return GetScaledImageName(fileName, scaledImgName, scaleFactor, scaledImageNameLength); }