JBR-1429 Scale is huge due to GDK_SCALE

(cherry picked from commit 1c3477df2e)
This commit is contained in:
Anton Tarasov
2019-07-29 19:00:37 +03:00
committed by alexey.ushakov@jetbrains.com
parent 3631619d80
commit 82f9e91e9c
5 changed files with 135 additions and 60 deletions

View File

@@ -1457,7 +1457,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel {
if (dpi < 50) {
dpi = 50;
}
X11GraphicsDevice.setGlobalDPI(dpi);
X11GraphicsDevice.setXftDpi(dpi);
}
}

View File

@@ -37,6 +37,7 @@ import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicBoolean;
import sun.awt.util.ThreadGroupUtils;
import sun.java2d.SunGraphicsEnvironment;
@@ -68,12 +69,27 @@ public final class X11GraphicsDevice extends GraphicsDevice
private DisplayMode origDisplayMode;
private boolean shutdownHookRegistered;
private int scale;
private volatile boolean isNativeScaleDefault;
private static int globalScale; // derived from Xft.dpi
private final AtomicBoolean isScaleFactorDefault = new AtomicBoolean(false);
private static final int XRM_XFT_DPI;
private static volatile int XFT_DPI;
private static final int GDK_SCALE;
private static final double GDK_DPI_SCALE;
private static final double GDK_SCALE_MULTIPLIER;
public X11GraphicsDevice(int screennum) {
this.screen = screennum;
this.scale = initScaleFactor();
int scaleFactor = initScaleFactor(-1);
synchronized (isScaleFactorDefault) {
isScaleFactorDefault.set(scaleFactor == -1);
this.scale = isScaleFactorDefault.get() ? 1 : scaleFactor;
}
}
static {
xrmXftDpi = getXrmXftDpi(-1);
GDK_SCALE = (int)getGdkScale("GDK_SCALE", -1);
GDK_DPI_SCALE = getGdkScale("GDK_DPI_SCALE", -1);
GDK_SCALE_MULTIPLIER = GDK_SCALE != -1 ? GDK_SCALE * (GDK_DPI_SCALE != -1 ? GDK_DPI_SCALE : 1) : 1;
}
/**
@@ -297,8 +313,11 @@ public final class X11GraphicsDevice extends GraphicsDevice
private static native void configDisplayMode(int screen,
int width, int height,
int displayMode);
private static native double getNativeScaleFactor(int screen);
private static native void resetNativeData(int screen);
private native Rectangle pGetBounds(int screenNum);
private static native double getNativeScaleFactor(int screen, double defValue);
private static native double getGdkScale(String name, double defValue);
private static native int getXrmXftDpi(int defValue);
/**
* Returns true only if:
@@ -506,7 +525,7 @@ public final class X11GraphicsDevice extends GraphicsDevice
*/
@Override
public synchronized void displayChanged() {
scale = initScaleFactor();
scale = initScaleFactor(1);
// On X11 the visuals do not change, and therefore we don't need
// to reset the defaultConfig, config, doubleBufferVisuals,
// neither do we need to reset the native data.
@@ -536,39 +555,66 @@ public final class X11GraphicsDevice extends GraphicsDevice
return scale;
}
public int getNativeScale() {
return (int)Math.round(getNativeScaleFactor(screen));
private double getNativeScale() {
isXrandrExtensionSupported();
return getNativeScaleFactor(screen, -1);
}
public static void setGlobalDPI(int dpi) {
public static void setXftDpi(int dpi) {
XFT_DPI = dpi;
boolean uiScaleEnabled = SunGraphicsEnvironment.isUIScaleEnabled(dpi);
globalScale = uiScaleEnabled ? (int)Math.round(dpi / 96.0) : 1;
double xftDpiScale = uiScaleEnabled ? XFT_DPI / 96.0 : 1.0;
for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
X11GraphicsDevice x11gd = (X11GraphicsDevice)gd;
if (x11gd.isNativeScaleDefault || !uiScaleEnabled) {
x11gd.scale = globalScale;
x11gd.isNativeScaleDefault = false;
synchronized (x11gd.isScaleFactorDefault) {
if (x11gd.isScaleFactorDefault.get() || !uiScaleEnabled) {
x11gd.scale = (int)Math.round(xftDpiScale * (uiScaleEnabled ? GDK_SCALE_MULTIPLIER : 1));
x11gd.isScaleFactorDefault.set(false);
}
}
}
}
private int initScaleFactor() {
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
private int initScaleFactor(int defValue) {
boolean uiScaleEnabled = SunGraphicsEnvironment.isUIScaleEnabled();
if (uiScaleEnabled) {
double debugScale = SunGraphicsEnvironment.getDebugScale();
if (debugScale >= 1) {
return (int) debugScale;
}
int nativeScale = getNativeScale();
if (nativeScale > 0) return nativeScale;
if (globalScale > 0) return globalScale;
isNativeScaleDefault = true;
return 1;
double gdkScaleMult = uiScaleEnabled ? GDK_SCALE_MULTIPLIER : 1;
double nativeScale = getNativeScale();
if (nativeScale > 0) {
return (int)Math.round(nativeScale * gdkScaleMult);
}
if (XRM_XFT_DPI > 0) {
return (int)Math.round((XRM_XFT_DPI / 96.0) * gdkScaleMult);
}
if (XFT_DPI > 0) {
return (int)Math.round((XFT_DPI / 96.0) * gdkScaleMult);
}
}
return defValue;
}
return 1;
/**
* Used externally for diagnostic purpose.
*/
public String[][] getDpiInfo() {
int xftDpi = XRM_XFT_DPI != -1 ? XRM_XFT_DPI : XFT_DPI;
String xftDpiStr = xftDpi != -1 ? String.valueOf(xftDpi) : "undefined";
double gsettingsScale = getNativeScaleFactor(screen, -1);
String gsettingsScaleStr = gsettingsScale != -1 ? String.valueOf(gsettingsScale) : "undefined";
String gdkScaleStr = GDK_SCALE != -1 ? String.valueOf(GDK_SCALE) : "undefined";
String gdkDpiScaleStr = GDK_DPI_SCALE != -1 ? String.valueOf(GDK_DPI_SCALE) : "undefined";
return new String[][] {
{"Xft.DPI", xftDpiStr, "Font DPI (X resources value)"},
{"GSettings scale factor", gsettingsScaleStr, "http://wiki.archlinux.org/index.php/HiDPI"},
{"GDK_SCALE", gdkScaleStr, "http://developer.gnome.org/gtk3/stable/gtk-x11.html"},
{"GDK_DPI_SCALE", gdkDpiScaleStr, "http://developer.gnome.org/gtk3/stable/gtk-x11.html"}
};
}
/**

View File

@@ -31,6 +31,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#ifdef __APPLE__
# include <xlocale.h>
#endif
typedef void* g_settings_schema_source_get_default();
typedef void* g_settings_schema_source_ref(void *);
@@ -204,16 +209,17 @@ static double getDesktopScale(char *output_name) {
}
static int getScale(const char *name) {
double getScaleEnvVar(const char *name, double default_value) {
char *uiScale = getenv(name);
if (uiScale != NULL) {
double scale = strtod(uiScale, NULL);
if (scale < 1) {
return -1;
locale_t c_locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
double scale = strtod_l(uiScale, NULL, c_locale);
freelocale(c_locale);
if (scale > 0) {
return scale;
}
return (int) scale;
}
return -1;
return default_value;
}
double getNativeScaleFactor(char *output_name, double default_value) {
@@ -222,7 +228,7 @@ double getNativeScaleFactor(char *output_name, double default_value) {
int gdk_scale = 0;
if (scale == -2) {
scale = getScale("J2D_UISCALE");
scale = (int)getScaleEnvVar("J2D_UISCALE", -1);
}
if (scale > 0) {
@@ -235,7 +241,5 @@ double getNativeScaleFactor(char *output_name, double default_value) {
native_scale = default_value;
}
gdk_scale = getScale("GDK_SCALE");
return gdk_scale > 0 ? (native_scale <= 0 ? 1 : native_scale) * gdk_scale : native_scale;
return native_scale;
}

View File

@@ -29,6 +29,7 @@
#include <stdlib.h>
double getNativeScaleFactor(char *output_name, double default_value);
double getScaleEnvVar(const char* var_name, double default_value);
#endif

View File

@@ -2057,40 +2057,64 @@ static char *get_output_screen_name(JNIEnv *env, int screen) {
/*
* Class: sun_awt_X11GraphicsDevice
* Method: getNativeScaleFactor
* Signature: (I)D
* Signature: (ID)D
*/
JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor
(JNIEnv *env, jobject this, jint screen) {
(JNIEnv *env, jobject this, jint screen, jdouble defValue) {
// in case of Xinerama individual screen scales are not supported
char *name = get_output_screen_name(env, usingXinerama ? 0 : screen);
double scale = getNativeScaleFactor(name, -1);
#ifndef HEADLESS
// Ubuntu 18.04 introduced a new settings for a scale factor: Settings > Devices > Displays > Scale.
// It is propagated to Xresource (and is read fine with 'xrdb' util) but is not propagated to GSettings
// (gtk3 doesn't see it in 'gtk-xft-dpi'). So, retrieve "Xft.dpi" from Xresource via X11 API call.
if (scale <= 0) {
Display *display = XOpenDisplay(NULL); // need to open new display to get up-to-date XResource value
if (display) {
char *resource_manager = XResourceManagerString(display);
if (resource_manager) {
XrmDatabase db = XrmGetStringDatabase(resource_manager);
if (db) {
XrmValue value;
char *type;
if (XrmGetResource(db, "Xft.dpi", "Xft.dpi", &type, &value)) {
scale = (double)atoi(value.addr) / 96;
}
}
}
XCloseDisplay(display);
}
}
#endif
double scale = getNativeScaleFactor(name, defValue);
if (name) {
free(name);
}
return scale;
}
/*
* Class: sun_awt_X11GraphicsDevice
* Method: getGdkScale
* Signature: (Ljava/lang/String;D)D
*/
JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsDevice_getGdkScale
(JNIEnv *env, jobject this, jstring envVarName, jdouble defValue)
{
const char* name = (*env)->GetStringUTFChars(env, envVarName, 0);
double value = getScaleEnvVar(name, defValue);
(*env)->ReleaseStringUTFChars(env, envVarName, name);
return value;
}
/*
* Class: sun_awt_X11GraphicsDevice
* Method: getXrmXftDpi
* Signature: (I)I
*/
JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getXrmXftDpi
(JNIEnv *env, jobject this, jint defValue)
{
int dpi = defValue;
#ifndef HEADLESS
// Ubuntu 18.04 introduced a new settings for a scale factor: Settings > Devices > Displays > Scale.
// It is propagated to Xresource (and is read fine with 'xrdb' util) but is not propagated to GSettings
// (gtk3 doesn't see it in 'gtk-xft-dpi'). So, retrieve "Xft.dpi" from Xresource via X11 API call.
Display *display = XOpenDisplay(NULL); // need to open new display to get up-to-date XResource value
if (display) {
char *resource_manager = XResourceManagerString(display);
if (resource_manager) {
XrmDatabase db = XrmGetStringDatabase(resource_manager);
if (db) {
XrmValue value;
char *type;
if (XrmGetResource(db, "Xft.dpi", "Xft.dpi", &type, &value)) {
dpi = atoi(value.addr);
}
}
}
XCloseDisplay(display);
}
#endif
return dpi;
}