X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fbin%2FHiDPISetting.java;h=d787388d447e88dff15081670cff47c5fc67aef6;hb=57738a1f3c19b1c3a00bd3ac5108f8cd0af32f99;hp=5e20d7658cfd6fa952bb069c2791c67be948e309;hpb=1e26a902b2a53081ab6035d43c2bdf13f1a7ee4e;p=jalview.git diff --git a/src/jalview/bin/HiDPISetting.java b/src/jalview/bin/HiDPISetting.java index 5e20d76..d787388 100644 --- a/src/jalview/bin/HiDPISetting.java +++ b/src/jalview/bin/HiDPISetting.java @@ -1,48 +1,241 @@ package jalview.bin; -import java.awt.Toolkit; +import java.util.Locale; + +import java.awt.HeadlessException; public class HiDPISetting { - public static final int dpi; + private static final int hidpiThreshold = 160; + + private static final int hidpiMultiThreshold = 240; + + private static final int bigScreenThreshold = 1400; + + public static final String scalePropertyName = "sun.java2d.uiScale"; + + private static final boolean isLinux; + + // private static final boolean isAMac; + + // private static final boolean isWindows; + + public static final String setHiDPIPropertyName = "setHiDPI"; + + public static final String setHiDPIScalePropertyName = "setHiDPIScale"; - public static final int scale; + private static boolean setHiDPI = false; - private static final int hidpi = 110; + private static int setHiDPIScale = 0; - private static final String scaleProperty = "sun.java2d.uiScale"; + public static int dpi = 0; - private static final boolean isAMac = System.getProperty("os.name") - .indexOf("Mac") > -1; + public static int mindimension = 0; - private static final boolean isLinux = System.getProperty("os.name") - .toLowerCase().indexOf("linux") > -1; + public static int width = 0; - private static final boolean isWindows = System.getProperty("os.name") - .toLowerCase().indexOf("windows") > -1; + public static int scale = 0; + + public final static int MAX_SCALE = 8; + + private static boolean doneInit = false; + + private static boolean allowScalePropertyArg = false; + + private static ScreenInfo screenInfo = new ScreenInfo(); static { - dpi = Toolkit.getDefaultToolkit().getScreenResolution(); - scale = dpi / hidpi + 1; - if (scale > 1 && isLinux) + String system = System.getProperty("os.name") == null ? null + : System.getProperty("os.name").toLowerCase(Locale.ROOT); + if (system != null) { - System.out.println("DPI detected as " + dpi - + ". Scaling factor set to " + scale + "."); + isLinux = system.indexOf("linux") > -1; + // isAMac = system.indexOf("mac") > -1; + // isWindows = system.indexOf("windows") > -1; + } + else + { + isLinux = false; + // isAMac = isWindows = false; } } - public static String getScalePropertyArg() + private static void init() { - // HiDPI setting. Just looking at Linux to start with. Test with Windows. - if (!isLinux) + if (doneInit) + { + return; + } + + // get and use command line property values first + String setHiDPIProperty = System.getProperty(setHiDPIPropertyName); + boolean setHiDPIPropertyBool = Boolean.parseBoolean(setHiDPIProperty); + + // allow -DsetHiDPI=false to turn off HiDPI scaling + if (setHiDPIProperty != null && !setHiDPIPropertyBool) + { + clear(); + doneInit = true; + return; + } + + setHiDPI = setHiDPIProperty != null && setHiDPIPropertyBool; + + String setHiDPIScaleProperty = System + .getProperty(setHiDPIScalePropertyName); + if (setHiDPIScaleProperty != null) + { + try + { + setHiDPIScale = Integer.parseInt(setHiDPIScaleProperty); + // if setHiDPIScale property is validly set and setHiDPI property wasn't + // attempted to be set we assume setHiDPIScale to be true + if (setHiDPIProperty == null) + { + setHiDPI = true; + } + } catch (NumberFormatException e) + { + System.err.println(setHiDPIScalePropertyName + " property give (" + + setHiDPIScaleProperty + ") but not parseable as integer"); + } + } + if (setHiDPI && setHiDPIScale > 0) + { + setHiDPIScale(setHiDPIScale); + return; + } + + // check to see if the scale property has already been set by something else + // (e.g. the OS) + String existingProperty = System.getProperty(scalePropertyName); + if (existingProperty != null) + { + try + { + int existingPropertyVal = Integer.parseInt(existingProperty); + System.out.println("Existing " + scalePropertyName + " is " + + existingPropertyVal); + if (existingPropertyVal > 1) + { + setHiDPIScale(existingPropertyVal); + return; + } + } catch (NumberFormatException e) + { + System.out.println("Could not convert property " + scalePropertyName + + " vale '" + existingProperty + "' to number"); + } + } + + // Try and auto guess a good scale based on reported DPI (not trustworthy) + // and screen resolution (more trustworthy) + + // get screen dpi + screenInfo = getScreenInfo(); + try + { + dpi = screenInfo.getScreenResolution(); + } catch (HeadlessException e) + { + System.err.println("Cannot get screen resolution: " + e.getMessage()); + } + + // try and get screen size height and width + try + { + int height = screenInfo.getScreenHeight(); + int width = screenInfo.getScreenWidth(); + // using mindimension in case of portrait screens + mindimension = Math.min(height, width); + } catch (HeadlessException e) + { + System.err.println( + "Cannot get screen size height and width:" + e.getMessage()); + } + + // attempt at a formula for scaling based on screen dpi and mindimension. + // scale will be an integer >=1. This formula is based on some testing and + // guesswork! + + // scale based on reported dpi. if dpi>hidpiThreshold then scale=2+multiples + // of hidpiMultiThreshold (else scale=1) + // (e.g. dpi of 110 scales 1. dpi of 120 scales 2. dpi of 360 scales 3) + int dpiScale = (dpi - hidpiThreshold > 0) + ? 2 + ((dpi - hidpiThreshold) / hidpiMultiThreshold) + : 1; + + int dimensionScale = 1 + (mindimension / bigScreenThreshold); + + // reject outrageous values -- dpiScale in particular could be mistaken + if (dpiScale > MAX_SCALE) { - return null; + dpiScale = 1; } - if (scale > 1) + if (dimensionScale > MAX_SCALE) + { + dimensionScale = 1; + } + + // choose larger of dimensionScale or dpiScale (most likely dimensionScale + // as dpiScale often misreported) + int autoScale = Math.max(dpiScale, dimensionScale); + + // only make an automatic change if scale is changed and other conditions + // (OS is linux) apply, or if setHiDPI has been specified + if ((autoScale > 1 && isLinux) || setHiDPI) + { + setHiDPIScale(autoScale); + return; + } + + // looks like we're not doing any scaling + doneInit = true; + } + + public static void setHiDPIScale(int s) + { + scale = s; + allowScalePropertyArg = true; + doneInit = true; + } + + public static String getScalePropertyArg(int s) + { + return "-D" + scalePropertyName + "=" + String.valueOf(s); + } + + public static String getScalePropertyArg() + { + init(); + // HiDPI setting. Just looking at Linux to start with. Test with Windows. + return allowScalePropertyArg ? getScalePropertyArg(scale) : null; + } + + public static void clear() + { + setHiDPI = false; + setHiDPIScale = 0; + dpi = 0; + mindimension = 0; + width = 0; + scale = 0; + doneInit = false; + allowScalePropertyArg = false; + } + + public static void setScreenInfo(ScreenInfo si) + { + screenInfo = si; + } + + public static ScreenInfo getScreenInfo() + { + if (screenInfo == null) { - return "-D" + scaleProperty + "=" + scale; + screenInfo = new ScreenInfo(); } - return null; + return screenInfo; } }