3 import java.util.Locale;
5 import java.awt.HeadlessException;
7 public class HiDPISetting
9 private static final int hidpiThreshold = 160;
11 private static final int hidpiMultiThreshold = 240;
13 private static final int bigScreenThreshold = 1400;
15 public static final String scalePropertyName = "sun.java2d.uiScale";
17 private static final boolean isLinux;
19 // private static final boolean isAMac;
21 // private static final boolean isWindows;
23 public static final String setHiDPIPropertyName = "setHiDPI";
25 public static final String setHiDPIScalePropertyName = "setHiDPIScale";
27 private static boolean setHiDPI = false;
29 private static int setHiDPIScale = 0;
31 public static int dpi = 0;
33 public static int mindimension = 0;
35 public static int width = 0;
37 public static int scale = 0;
39 public final static int MAX_SCALE = 8;
41 private static boolean doneInit = false;
43 private static boolean allowScalePropertyArg = false;
45 private static ScreenInfo screenInfo = new ScreenInfo();
49 String system = System.getProperty("os.name") == null ? null
50 : System.getProperty("os.name").toLowerCase(Locale.ROOT);
53 isLinux = system.indexOf("linux") > -1;
54 // isAMac = system.indexOf("mac") > -1;
55 // isWindows = system.indexOf("windows") > -1;
60 // isAMac = isWindows = false;
64 private static void init()
71 // get and use command line property values first
72 String setHiDPIProperty = System.getProperty(setHiDPIPropertyName);
73 boolean setHiDPIPropertyBool = Boolean.parseBoolean(setHiDPIProperty);
75 // allow -DsetHiDPI=false to turn off HiDPI scaling
76 if (setHiDPIProperty != null && !setHiDPIPropertyBool)
83 setHiDPI = setHiDPIProperty != null && setHiDPIPropertyBool;
85 String setHiDPIScaleProperty = System
86 .getProperty(setHiDPIScalePropertyName);
87 if (setHiDPIScaleProperty != null)
91 setHiDPIScale = Integer.parseInt(setHiDPIScaleProperty);
92 // if setHiDPIScale property is validly set and setHiDPI property wasn't
93 // attempted to be set we assume setHiDPIScale to be true
94 if (setHiDPIProperty == null)
98 } catch (NumberFormatException e)
100 System.err.println(setHiDPIScalePropertyName + " property give ("
101 + setHiDPIScaleProperty + ") but not parseable as integer");
104 if (setHiDPI && setHiDPIScale > 0)
106 setHiDPIScale(setHiDPIScale);
110 // check to see if the scale property has already been set by something else
112 String existingProperty = System.getProperty(scalePropertyName);
113 if (existingProperty != null)
117 int existingPropertyVal = Integer.parseInt(existingProperty);
118 System.out.println("Existing " + scalePropertyName + " is "
119 + existingPropertyVal);
120 if (existingPropertyVal > 1)
122 setHiDPIScale(existingPropertyVal);
125 } catch (NumberFormatException e)
127 System.out.println("Could not convert property " + scalePropertyName
128 + " vale '" + existingProperty + "' to number");
132 // Try and auto guess a good scale based on reported DPI (not trustworthy)
133 // and screen resolution (more trustworthy)
136 screenInfo = getScreenInfo();
139 dpi = screenInfo.getScreenResolution();
140 } catch (HeadlessException e)
142 System.err.println("Cannot get screen resolution: " + e.getMessage());
145 // try and get screen size height and width
148 int height = screenInfo.getScreenHeight();
149 int width = screenInfo.getScreenWidth();
150 // using mindimension in case of portrait screens
151 mindimension = Math.min(height, width);
152 } catch (HeadlessException e)
155 "Cannot get screen size height and width:" + e.getMessage());
158 // attempt at a formula for scaling based on screen dpi and mindimension.
159 // scale will be an integer >=1. This formula is based on some testing and
162 // scale based on reported dpi. if dpi>hidpiThreshold then scale=2+multiples
163 // of hidpiMultiThreshold (else scale=1)
164 // (e.g. dpi of 110 scales 1. dpi of 120 scales 2. dpi of 360 scales 3)
165 int dpiScale = (dpi - hidpiThreshold > 0)
166 ? 2 + ((dpi - hidpiThreshold) / hidpiMultiThreshold)
169 int dimensionScale = 1 + (mindimension / bigScreenThreshold);
171 // reject outrageous values -- dpiScale in particular could be mistaken
172 if (dpiScale > MAX_SCALE) {
175 if (dimensionScale > MAX_SCALE) {
179 // choose larger of dimensionScale or dpiScale (most likely dimensionScale
180 // as dpiScale often misreported)
181 int autoScale = Math.max(dpiScale, dimensionScale);
183 // only make an automatic change if scale is changed and other conditions
184 // (OS is linux) apply, or if setHiDPI has been specified
185 if ((autoScale > 1 && isLinux) || setHiDPI)
187 setHiDPIScale(autoScale);
191 // looks like we're not doing any scaling
195 public static void setHiDPIScale(int s)
198 allowScalePropertyArg = true;
202 public static String getScalePropertyArg(int s)
204 return "-D" + scalePropertyName + "=" + String.valueOf(s);
207 public static String getScalePropertyArg()
210 // HiDPI setting. Just looking at Linux to start with. Test with Windows.
211 return allowScalePropertyArg ? getScalePropertyArg(scale) : null;
214 public static void clear()
223 allowScalePropertyArg = false;
226 public static void setScreenInfo(ScreenInfo si)
231 public static ScreenInfo getScreenInfo()
233 if (screenInfo == null)
235 screenInfo = new ScreenInfo();