Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ public static Optional<AutoScaleMethod> 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.
* <ul>
* <li>"true": the application is scaled on DPI changes</li>
* <li>"false": the application will remain in its initial scaling</li>
* </ul>
* <b>Important:</b> 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.
Expand Down Expand Up @@ -87,6 +98,14 @@ public static Optional<AutoScaleMethod> 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<String> ALLOWED_AUTOSCALE_VALUES_FOR_UPDATE_ON_RUNTIME = Set.of("quarter", "exact");

static {
autoScaleValue = System.getProperty (SWT_AUTOSCALE);

Expand All @@ -95,14 +114,47 @@ public static Optional<AutoScaleMethod> 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;
}

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:
* <ul>
* <li>Not running on Windows</li>
* <li>The current auto-scale mode is incompatible</li>
* </ul>
*
* <p>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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <ul>
* <li>"true": the application is scaled on DPI changes</li>
* <li>"false": the application will remain in its initial scaling</li>
* </ul>
* <b>Important:</b> 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());
}
Expand Down Expand Up @@ -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() {
Expand Down
Loading