Skip to content

Commit 0c71467

Browse files
[Refactor] Move autoscaling methods in AutoScaling class
A new utility solely responsible for taking care of autoscaling methods. Also introduced new system property swt.autoScale.force that can be set to true in order to disable the compatibility error for setting the autoscale value when update on runtime is enabled.
1 parent 485749a commit 0c71467

File tree

7 files changed

+125
-75
lines changed

7 files changed

+125
-75
lines changed

bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/ResetMonitorSpecificScalingExtension.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*******************************************************************************/
1111
package org.eclipse.swt.internal;
1212

13+
import org.eclipse.swt.*;
1314
import org.eclipse.swt.widgets.*;
1415
import org.junit.jupiter.api.extension.*;
1516

@@ -25,13 +26,13 @@ protected ResetMonitorSpecificScalingExtension() {
2526

2627
@Override
2728
public void beforeEach(ExtensionContext context) throws Exception {
28-
wasMonitorSpecificScalingActive = Win32DPIUtils.isMonitorSpecificScalingActive();
29+
wasMonitorSpecificScalingActive = AutoScaling.isMonitorSpecificScalingActive();
2930
Display.getDefault().dispose();
3031
}
3132

3233
@Override
3334
public void afterEach(ExtensionContext context) throws Exception {
34-
Win32DPIUtils.setMonitorSpecificScaling(wasMonitorSpecificScalingActive);
35+
AutoScaling.setMonitorSpecificScaling(wasMonitorSpecificScalingActive);
3536
Display.getDefault().dispose();
3637
DPIUtil.setDeviceZoom(100);
3738
}

bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/WithMonitorSpecificScalingExtension.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*******************************************************************************/
1111
package org.eclipse.swt.internal;
1212

13+
import org.eclipse.swt.*;
1314
import org.junit.jupiter.api.extension.*;
1415

1516
/**
@@ -24,7 +25,7 @@ private WithMonitorSpecificScalingExtension() {
2425
@Override
2526
public void beforeEach(ExtensionContext context) throws Exception {
2627
super.beforeEach(context);
27-
Win32DPIUtils.setMonitorSpecificScaling(true);
28+
AutoScaling.setMonitorSpecificScaling(true);
2829
}
2930

3031
}

bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/ControlWin32Tests.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class ControlWin32Tests {
3636

3737
@Test
3838
public void testScaleFontCorrectlyInAutoScaleScenario() {
39-
Win32DPIUtils.setMonitorSpecificScaling(true);
39+
AutoScaling.setMonitorSpecificScaling(true);
4040
Display display = Display.getDefault();
4141

4242
assertTrue("Autoscale property is not set to true", display.isRescalingAtRuntime());
@@ -48,7 +48,7 @@ public void testScaleFontCorrectlyInAutoScaleScenario() {
4848

4949
@Test
5050
public void testSetFontWithMonitorSpecificScalingEnabled() {
51-
Win32DPIUtils.setMonitorSpecificScaling(true);
51+
AutoScaling.setMonitorSpecificScaling(true);
5252
Display display = Display.getDefault();
5353
Image colorImage = new Image(display, 10, 10);
5454
GC gc = new GC(colorImage);
@@ -59,7 +59,7 @@ public void testSetFontWithMonitorSpecificScalingEnabled() {
5959

6060
@Test
6161
public void testDoNotScaleFontInNoAutoScaleScenario() {
62-
Win32DPIUtils.setMonitorSpecificScaling(false);
62+
AutoScaling.setMonitorSpecificScaling(false);
6363
Display display = Display.getDefault();
6464

6565
assertFalse("Autoscale property is not set to false", display.isRescalingAtRuntime());
@@ -71,7 +71,7 @@ public void testDoNotScaleFontInNoAutoScaleScenario() {
7171

7272
@Test
7373
public void testDoNotScaleFontInNoAutoScaleScenarioWithLegacyFontRegistry() {
74-
Win32DPIUtils.setMonitorSpecificScaling(false);
74+
AutoScaling.setMonitorSpecificScaling(false);
7575
String originalValue = System.getProperty("swt.fontRegistry");
7676
System.setProperty("swt.fontRegistry", "legacy");
7777
try {
@@ -93,7 +93,7 @@ public void testDoNotScaleFontInNoAutoScaleScenarioWithLegacyFontRegistry() {
9393

9494
@Test
9595
public void testCorrectScaleUpUsingDifferentSetBoundsMethod() {
96-
Win32DPIUtils.setMonitorSpecificScaling(true);
96+
AutoScaling.setMonitorSpecificScaling(true);
9797
Display display = Display.getDefault();
9898
Shell shell = new Shell(display);
9999
Button button = new Button(shell, SWT.PUSH);
@@ -114,7 +114,7 @@ public void testCorrectScaleUpUsingDifferentSetBoundsMethod() {
114114
@CsvSource({ "0.5, 100, true", "1.0, 200, true", "2.0, 200, true", "2.0, quarter, true", "0.5, 100, false",
115115
"1.0, 200, false", "2.0, 200, false", "2.0, quarter, false", })
116116
public void testAutoScaleImageData(float scaleFactor, String autoScale, boolean monitorSpecificScaling) {
117-
Win32DPIUtils.setMonitorSpecificScaling(monitorSpecificScaling);
117+
AutoScaling.setMonitorSpecificScaling(monitorSpecificScaling);
118118
DPIUtil.runWithAutoScaleValue(autoScale, () -> {
119119
Display display = new Display();
120120
try {

bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/DisplayWin32Test.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static org.junit.jupiter.api.Assertions.*;
44

5+
import org.eclipse.swt.*;
56
import org.eclipse.swt.internal.*;
67
import org.eclipse.swt.internal.win32.*;
78
import org.junit.jupiter.api.*;
@@ -13,15 +14,15 @@ class DisplayWin32Test {
1314

1415
@Test
1516
public void monitorSpecificScaling_activate() {
16-
Win32DPIUtils.setMonitorSpecificScaling(true);
17+
AutoScaling.setMonitorSpecificScaling(true);
1718
Display display = Display.getDefault();
1819
assertTrue(display.isRescalingAtRuntime());
1920
assertEquals(OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, OS.GetThreadDpiAwarenessContext());
2021
}
2122

2223
@Test
2324
public void monitorSpecificScaling_deactivate() {
24-
Win32DPIUtils.setMonitorSpecificScaling(false);
25+
AutoScaling.setMonitorSpecificScaling(false);
2526
Display display = Display.getDefault();
2627
assertFalse(display.isRescalingAtRuntime());
2728
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package org.eclipse.swt;
2+
3+
import java.util.*;
4+
5+
import org.eclipse.swt.internal.*;
6+
7+
/**
8+
* Utility for checking and enabling monitor-specific auto scaling.
9+
* @since 3.132
10+
*/
11+
public final class AutoScaling {
12+
/**
13+
* System property to enable to scale the application on runtime
14+
* when a DPI change is detected.
15+
* <ul>
16+
* <li>"true": the application is scaled on DPI changes</li>
17+
* <li>"false": the application will remain in its initial scaling</li>
18+
* </ul>
19+
* <b>Important:</b> This flag is only parsed and used on Win32. Setting it to
20+
* true on GTK or cocoa will be ignored.
21+
*/
22+
private static final String SWT_AUTOSCALE_UPDATE_ON_RUNTIME = "swt.autoScale.updateOnRuntime";
23+
private static final String SWT_AUTOSCALE = "swt.autoScale";
24+
private static final String SWT_AUTOSCALE_DISABLE_COMPATIBILITY_CHECK = "swt.autoScale.force";
25+
private static String autoScaleValue;
26+
static {
27+
autoScaleValue = System.getProperty (SWT_AUTOSCALE);
28+
}
29+
private static final Set<String> ALLOWED_VALUES = Set.of("false", "quarter", "exact");
30+
private static final String WIN32_PLATFORM = "win32";
31+
32+
public static String getAutoScaleValue() {
33+
return autoScaleValue;
34+
}
35+
36+
/**
37+
* Returns {@code true} only if the current setup is compatible
38+
* with monitor-specific scaling. Returns {@code false} if:
39+
* <ul>
40+
* <li>Not running on Windows</li>
41+
* <li>The current auto-scale mode is incompatible</li>
42+
* </ul>
43+
*
44+
*/
45+
public static boolean isSetupCompatibleToMonitorSpecificScaling() {
46+
if("true".equalsIgnoreCase(System.getProperty(SWT_AUTOSCALE_DISABLE_COMPATIBILITY_CHECK))) {
47+
return true;
48+
}
49+
// Per-monitor DPI supported only on Windows
50+
if (!isWindows()) {
51+
return false;
52+
}
53+
54+
// Default means: treat as "quarter" (compatible)
55+
if (autoScaleValue == null) {
56+
return true;
57+
}
58+
59+
String value = autoScaleValue.toLowerCase(Locale.ROOT);
60+
61+
// Compatible only if one of the known values
62+
return ALLOWED_VALUES.contains(value);
63+
}
64+
65+
/**
66+
* Enables monitor-specific scaling *regardless of compatibility*.
67+
*/
68+
public static void enableMonitorSpecificScaling() {
69+
System.setProperty(SWT_AUTOSCALE_UPDATE_ON_RUNTIME, "true");
70+
}
71+
72+
public static void setAutoScaleForMonitorSpecificScaling() {
73+
boolean isDefaultAutoScale = autoScaleValue == null;
74+
if (isDefaultAutoScale) {
75+
autoScaleValue = "quarter";
76+
}
77+
}
78+
79+
public static boolean isMonitorSpecificScalingActive() {
80+
boolean updateOnRuntimeValue = Boolean.getBoolean (SWT_AUTOSCALE_UPDATE_ON_RUNTIME);
81+
return updateOnRuntimeValue;
82+
}
83+
84+
/**
85+
* Runs the given {@link Runnable} under a temporarily applied auto-scale
86+
* value, restoring the previous value afterwards. Intended as the public
87+
* replacement for the internal DPIUtil#runWithAutoScaleValue().
88+
*/
89+
public static void runWithAutoScaleValue(String autoScaleValue, Runnable code) {
90+
String initialAutoScaleValue = autoScaleValue;
91+
AutoScaling.autoScaleValue = autoScaleValue;
92+
DPIUtil.setDeviceZoom(DPIUtil.getZoomForAutoscaleProperty(DPIUtil.getNativeDeviceZoom()));
93+
try {
94+
code.run();
95+
} finally {
96+
AutoScaling.autoScaleValue = initialAutoScaleValue;
97+
DPIUtil.setDeviceZoom(DPIUtil.getZoomForAutoscaleProperty(DPIUtil.getNativeDeviceZoom()));
98+
}
99+
}
100+
101+
private static boolean isWindows() {
102+
return WIN32_PLATFORM.equals(SWT.getPlatform());
103+
}
104+
105+
public static void setMonitorSpecificScaling(boolean activate) {
106+
System.setProperty(SWT_AUTOSCALE_UPDATE_ON_RUNTIME, Boolean.toString(activate));
107+
}
108+
}

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,9 @@
3333
* @noreference This class is not intended to be referenced by clients
3434
*/
3535
public class Win32DPIUtils {
36-
/**
37-
* System property to enable to scale the application on runtime
38-
* when a DPI change is detected.
39-
* <ul>
40-
* <li>"true": the application is scaled on DPI changes</li>
41-
* <li>"false": the application will remain in its initial scaling</li>
42-
* </ul>
43-
* <b>Important:</b> This flag is only parsed and used on Win32. Setting it to
44-
* true on GTK or cocoa will be ignored.
45-
*/
46-
private static final String SWT_AUTOSCALE_UPDATE_ON_RUNTIME = "swt.autoScale.updateOnRuntime";
4736

4837
static {
49-
DPIUtil.setUseSmoothScalingByDefaultProvider(() -> isMonitorSpecificScalingActive());
38+
DPIUtil.setUseSmoothScalingByDefaultProvider(() -> AutoScaling.isMonitorSpecificScalingActive());
5039
}
5140

5241
public static boolean setDPIAwareness(int desiredDpiAwareness) {
@@ -277,56 +266,6 @@ public static Rectangle pointToPixel(Drawable drawable, Rectangle rect, int zoom
277266
return pointToPixel (rect, zoom);
278267
}
279268

280-
public static void setMonitorSpecificScaling(boolean activate) {
281-
System.setProperty(SWT_AUTOSCALE_UPDATE_ON_RUNTIME, Boolean.toString(activate));
282-
}
283-
284-
public static void setAutoScaleForMonitorSpecificScaling() {
285-
boolean isDefaultAutoScale = DPIUtil.getAutoScaleValue() == null;
286-
if (isDefaultAutoScale) {
287-
DPIUtil.setAutoScaleValue("quarter");
288-
} else if (!isSupportedAutoScaleForMonitorSpecificScaling()) {
289-
throw new SWTError(SWT.ERROR_NOT_IMPLEMENTED,
290-
"monitor-specific scaling is only implemented for auto-scale values \"quarter\", \"exact\", \"false\" or a concrete zoom value, but \""
291-
+ DPIUtil.getAutoScaleValue() + "\" has been specified");
292-
}
293-
}
294-
295-
/**
296-
* Monitor-specific scaling on Windows only supports auto-scale modes in which
297-
* all elements (font, images, control bounds etc.) are scaled equally or almost
298-
* equally. The previously default mode "integer"/"integer200", which rounded
299-
* the scale factor for everything but fonts to multiples of 100, is complex and
300-
* difficult to realize with monitor-specific rescaling of UI elements. Since a
301-
* uniform scale factor for everything should perspectively be used anyway,
302-
* there will be support for complex auto-scale modes for monitor-specific
303-
* scaling.
304-
*
305-
* The supported modes are "quarter" and "exact" or explicit zoom values given
306-
* by the value itself or "false". Every other value will be treated as
307-
* "integer"/"integer200" and is thus not supported.
308-
*/
309-
private static boolean isSupportedAutoScaleForMonitorSpecificScaling() {
310-
if (DPIUtil.getAutoScaleValue() == null) {
311-
return false;
312-
}
313-
switch (DPIUtil.getAutoScaleValue().toLowerCase()) {
314-
case "false", "quarter", "exact": return true;
315-
}
316-
try {
317-
Integer.parseInt(DPIUtil.getAutoScaleValue());
318-
return true;
319-
} catch (NumberFormatException e) {
320-
// unsupported value, use default
321-
}
322-
return false;
323-
}
324-
325-
public static boolean isMonitorSpecificScalingActive() {
326-
boolean updateOnRuntimeValue = Boolean.getBoolean (SWT_AUTOSCALE_UPDATE_ON_RUNTIME);
327-
return updateOnRuntimeValue;
328-
}
329-
330269
public static int getPrimaryMonitorZoomAtStartup() {
331270
long hDC = OS.GetDC(0);
332271
int dpi = OS.GetDeviceCaps(hDC, OS.LOGPIXELSX);

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -949,9 +949,9 @@ public void close () {
949949
protected void create (DeviceData data) {
950950
checkSubclass ();
951951
checkDisplay (thread = Thread.currentThread (), true);
952-
if (Win32DPIUtils.isMonitorSpecificScalingActive()) {
952+
if (AutoScaling.isMonitorSpecificScalingActive()) {
953953
setMonitorSpecificScaling(true);
954-
Win32DPIUtils.setAutoScaleForMonitorSpecificScaling();
954+
AutoScaling.setAutoScaleForMonitorSpecificScaling();
955955
}
956956
createDisplay (data);
957957
register (this);

0 commit comments

Comments
 (0)