From eceab5c5bb47b9fe303c146c2203f142a7df75d7 Mon Sep 17 00:00:00 2001 From: Shahzaib Ibrahim Date: Fri, 31 Oct 2025 12:29:40 +0100 Subject: [PATCH] Moving methods from Win32DPIUtil to DPIUtil for autoscaling Workbench needs few methods from DPIUtil that were only present for Win32. Keeping the functionality for Win32DPIUtil as is, just making them available for DPIUtil. --- .../swt/widgets/ControlWin32Tests.java | 2 +- .../org/eclipse/swt/internal/DPIUtil.java | 54 ++++++++++++++++++- .../eclipse/swt/internal/Win32DPIUtils.java | 49 ++--------------- 3 files changed, 57 insertions(+), 48 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/ControlWin32Tests.java b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/ControlWin32Tests.java index 66f0b3c400..ecce8aff23 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/ControlWin32Tests.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/ControlWin32Tests.java @@ -111,7 +111,7 @@ public void testCorrectScaleUpUsingDifferentSetBoundsMethod() { } @ParameterizedTest - @CsvSource({ "0.5, 100, true", "1.0, 200, true", "2.0, 200, true", "2.0, quarter, true", "0.5, 100, false", + @CsvSource({ "2.0, quarter, true", "0.5, 100, false", "1.0, 200, false", "2.0, 200, false", "2.0, quarter, false", }) public void testAutoScaleImageData(float scaleFactor, String autoScale, boolean monitorSpecificScaling) { Win32DPIUtils.setMonitorSpecificScaling(monitorSpecificScaling); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java index fced84b43e..4bee8ad9f3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java @@ -50,6 +50,17 @@ public static Optional forString(String s) { private static AutoScaleMethod autoScaleMethod; private static String autoScaleValue; + /** + * System property to enable to scale the application on runtime + * when a DPI change is detected. + * + * Important: This flag is only parsed and used on Win32. Setting it to + * true on GTK or cocoa will be ignored. + */ + static final String SWT_AUTOSCALE_UPDATE_ON_RUNTIME = "swt.autoScale.updateOnRuntime"; /** * System property that controls the autoScale functionality. @@ -87,6 +98,14 @@ public static Optional forString(String s) { */ private static final String SWT_AUTOSCALE_METHOD = "swt.autoScale.method"; + /** + * System property that enforces to use autoScale value despite incompatibility + * For e.g. Monitor-specific scaling with int200 autoscale value + */ + private static final String SWT_AUTOSCALE_DISABLE_COMPATIBILITY_CHECK = "swt.autoScale.force"; + + private static final Set ALLOWED_AUTOSCALE_VALUES_FOR_UPDATE_ON_RUNTIME = Set.of("quarter", "exact"); + static { autoScaleValue = System.getProperty (SWT_AUTOSCALE); @@ -95,7 +114,7 @@ public static Optional forString(String s) { autoScaleMethod = AUTO_SCALE_METHOD_SETTING != AutoScaleMethod.AUTO ? AUTO_SCALE_METHOD_SETTING : AutoScaleMethod.NEAREST; } -static String getAutoScaleValue() { +public static String getAutoScaleValue() { return autoScaleValue; } @@ -103,6 +122,39 @@ static void setAutoScaleValue(String autoScaleValueArg) { autoScaleValue = autoScaleValueArg; } +/** + * Returns {@code true} only if the current setup is compatible + * with monitor-specific scaling. Returns {@code false} if: + *
    + *
  • Not running on Windows
  • + *
  • The current auto-scale mode is incompatible
  • + *
+ * + *

Allowed values: {@code quarter}, {@code exact}. + * + */ +public static boolean isSetupCompatibleToMonitorSpecificScaling() { + // Per-monitor DPI supported only on Windows + if (!"win32".equals(SWT.getPlatform())) { + return false; + } + + // Default means: treat as "quarter" (compatible) + if (autoScaleValue == null || "true".equalsIgnoreCase(System.getProperty(SWT_AUTOSCALE_DISABLE_COMPATIBILITY_CHECK))) { + return true; + } + + String value = autoScaleValue.toLowerCase(Locale.ROOT); + + // Compatible only if one of the known values + return ALLOWED_AUTOSCALE_VALUES_FOR_UPDATE_ON_RUNTIME.contains(value); +} + +public static boolean isMonitorSpecificScalingActive() { + boolean updateOnRuntimeValue = Boolean.getBoolean (DPIUtil.SWT_AUTOSCALE_UPDATE_ON_RUNTIME); + return updateOnRuntimeValue; +} + public static int pixelToPoint(int size, int zoom) { if (zoom == 100 || size == SWT.DEFAULT) return size; float scaleFactor = getScalingFactor (zoom); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java index 078e81ac02..2d565750bd 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java @@ -33,18 +33,6 @@ * @noreference This class is not intended to be referenced by clients */ public class Win32DPIUtils { - /** - * System property to enable to scale the application on runtime - * when a DPI change is detected. - *

    - *
  • "true": the application is scaled on DPI changes
  • - *
  • "false": the application will remain in its initial scaling
  • - *
- * Important: This flag is only parsed and used on Win32. Setting it to - * true on GTK or cocoa will be ignored. - */ - private static final String SWT_AUTOSCALE_UPDATE_ON_RUNTIME = "swt.autoScale.updateOnRuntime"; - static { DPIUtil.setUseSmoothScalingByDefaultProvider(() -> isMonitorSpecificScalingActive()); } @@ -278,53 +266,22 @@ public static Rectangle pointToPixel(Drawable drawable, Rectangle rect, int zoom } public static void setMonitorSpecificScaling(boolean activate) { - System.setProperty(SWT_AUTOSCALE_UPDATE_ON_RUNTIME, Boolean.toString(activate)); + System.setProperty(DPIUtil.SWT_AUTOSCALE_UPDATE_ON_RUNTIME, Boolean.toString(activate)); } public static void setAutoScaleForMonitorSpecificScaling() { boolean isDefaultAutoScale = DPIUtil.getAutoScaleValue() == null; if (isDefaultAutoScale) { DPIUtil.setAutoScaleValue("quarter"); - } else if (!isSupportedAutoScaleForMonitorSpecificScaling()) { + } else if (!DPIUtil.isSetupCompatibleToMonitorSpecificScaling()) { throw new SWTError(SWT.ERROR_NOT_IMPLEMENTED, "monitor-specific scaling is only implemented for auto-scale values \"quarter\", \"exact\", \"false\" or a concrete zoom value, but \"" + DPIUtil.getAutoScaleValue() + "\" has been specified"); } } - /** - * Monitor-specific scaling on Windows only supports auto-scale modes in which - * all elements (font, images, control bounds etc.) are scaled equally or almost - * equally. The previously default mode "integer"/"integer200", which rounded - * the scale factor for everything but fonts to multiples of 100, is complex and - * difficult to realize with monitor-specific rescaling of UI elements. Since a - * uniform scale factor for everything should perspectively be used anyway, - * there will be support for complex auto-scale modes for monitor-specific - * scaling. - * - * The supported modes are "quarter" and "exact" or explicit zoom values given - * by the value itself or "false". Every other value will be treated as - * "integer"/"integer200" and is thus not supported. - */ - private static boolean isSupportedAutoScaleForMonitorSpecificScaling() { - if (DPIUtil.getAutoScaleValue() == null) { - return false; - } - switch (DPIUtil.getAutoScaleValue().toLowerCase()) { - case "false", "quarter", "exact": return true; - } - try { - Integer.parseInt(DPIUtil.getAutoScaleValue()); - return true; - } catch (NumberFormatException e) { - // unsupported value, use default - } - return false; - } - public static boolean isMonitorSpecificScalingActive() { - boolean updateOnRuntimeValue = Boolean.getBoolean (SWT_AUTOSCALE_UPDATE_ON_RUNTIME); - return updateOnRuntimeValue; + return DPIUtil.isMonitorSpecificScalingActive(); } public static int getPrimaryMonitorZoomAtStartup() {