diff --git a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/DPITestUtil.java b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/DPITestUtil.java deleted file mode 100644 index 2397eec0df5..00000000000 --- a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/DPITestUtil.java +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2024 Yatta Solutions - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ -package org.eclipse.swt.internal; - -public final class DPITestUtil { - private DPITestUtil() { - } - - public static void setAutoScaleOnRunTime(boolean value) { - DPIUtil.setAutoScaleOnRuntimeActive(value); - } - - public static boolean isAutoScaleOnRuntimeActive() { - return DPIUtil.isAutoScaleOnRuntimeActive(); - } -} diff --git a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/Win32AutoscaleTestBase.java b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/Win32AutoscaleTestBase.java index bb5267cc300..2710a4fa704 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/Win32AutoscaleTestBase.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/internal/Win32AutoscaleTestBase.java @@ -20,7 +20,6 @@ public abstract class Win32AutoscaleTestBase { protected Display display; protected Shell shell; - private boolean autoScaleOnRuntime; @BeforeAll public static void assumeIsFittingPlatform() { @@ -29,9 +28,8 @@ public static void assumeIsFittingPlatform() { @BeforeEach public void setUpTest() { - autoScaleOnRuntime = DPITestUtil.isAutoScaleOnRuntimeActive(); display = Display.getDefault(); - autoScaleOnRuntime(true); + display.setRescalingAtRuntime(true); shell = new Shell(display); } @@ -40,13 +38,7 @@ public void tearDownTest() { if (shell != null) { shell.dispose(); } - autoScaleOnRuntime(autoScaleOnRuntime); - } - - protected void autoScaleOnRuntime (boolean autoScaleOnRuntime) { - DPITestUtil.setAutoScaleOnRunTime(autoScaleOnRuntime); - // dispose a existing font registry for the default display - SWTFontProvider.disposeFontRegistry(display); + display.dispose(); } protected void changeDPIZoom (int nativeZoom) { 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 206560c2fd6..de94f253dda 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 @@ -30,7 +30,7 @@ class ControlWin32Tests extends Win32AutoscaleTestBase { @Test public void testScaleFontCorrectlyInAutoScaleSzenario() { - assertTrue("Autoscale property is not set to true", DPITestUtil.isAutoScaleOnRuntimeActive()); + assertTrue("Autoscale property is not set to true", display.isRescalingAtRuntime()); int scalingFactor = 2; Control control = new Composite(shell, SWT.NONE); @@ -54,8 +54,8 @@ public void testScaleFontCorrectlyInAutoScaleSzenario() { @Test public void testDoNotScaleFontCorrectlyInNoAutoScaleSzenario() { - autoScaleOnRuntime(false); - assertFalse("Autoscale property is not set to false", DPITestUtil.isAutoScaleOnRuntimeActive()); + display.setRescalingAtRuntime(false); + assertFalse("Autoscale property is not set to false", display.isRescalingAtRuntime()); int scalingFactor = 2; Control control = new Composite(shell, SWT.NONE); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java index c1abd1a31bf..ecf7d471a73 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java @@ -6832,4 +6832,33 @@ static long windowProc(long id, long sel, long arg0, long arg1, long arg2, long static boolean isActivateShellOnForceFocus() { return "true".equals(System.getProperty("org.eclipse.swt.internal.activateShellOnForceFocus", "true")); //$NON-NLS-1$ } + +/** + * {@return whether rescaling of shells at runtime when the DPI scaling of a + * shell's monitor changes is activated for this device} + *
+ * Note: This functionality is only available on Windows. Calling this + * method on other operating system will always return false. + * + * @since 3.127 + */ +public boolean isRescalingAtRuntime() { + return false; +} + +/** + * Activates or deactivates rescaling of shells at runtime whenever the DPI + * scaling of the shell's monitor changes. This is only safe to call as long as + * no shell has been created for this display. When changing the value after a + * shell has been created for this display, the effect is undefined. + *
+ * Note: This functionality is only available on Windows. Calling this + * method on other operating system will have no effect. + * + * @param activate whether rescaling shall be activated or deactivated + * @since 3.127 + */ +public void setRescalingAtRuntime(boolean activate) { + // not implemented for Cocoa +} } 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 81e67b8ba59..592d5ac01dd 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 @@ -110,10 +110,8 @@ private static enum AutoScaleMethod { AUTO, NEAREST, SMOOTH } } } - if ("win32".equals(SWT.getPlatform())) { - String updateOnRuntimeValue = System.getProperty (SWT_AUTOSCALE_UPDATE_ON_RUNTIME); - autoScaleOnRuntime = Boolean.parseBoolean(updateOnRuntimeValue); - } + String updateOnRuntimeValue = System.getProperty (SWT_AUTOSCALE_UPDATE_ON_RUNTIME); + autoScaleOnRuntime = Boolean.parseBoolean(updateOnRuntimeValue); } /** @@ -669,10 +667,6 @@ public static boolean isAutoScaleOnRuntimeActive() { return autoScaleOnRuntime; } -static boolean setAutoScaleOnRuntimeActive(boolean value) { - return autoScaleOnRuntime = value; -} - /** * AutoScale ImageDataProvider. */ diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java index 0d5e14e746c..0e1ed40617a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java @@ -6266,4 +6266,34 @@ static int _getDeviceZoom (long monitor_num) { static boolean isActivateShellOnForceFocus() { return "true".equals(System.getProperty("org.eclipse.swt.internal.activateShellOnForceFocus", "true")); //$NON-NLS-1$ } + +/** + * {@return whether rescaling of shells at runtime when the DPI scaling of a + * shell's monitor changes is activated for this device} + *
+ * Note: This functionality is only available on Windows. Calling this + * method on other operating system will always return false. + * + * @since 3.127 + */ +public boolean isRescalingAtRuntime() { + return false; +} + +/** + * Activates or deactivates rescaling of shells at runtime whenever the DPI + * scaling of the shell's monitor changes. This is only safe to call as long as + * no shell has been created for this display. When changing the value after a + * shell has been created for this display, the effect is undefined. + *
+ * Note: This functionality is only available on Windows. Calling this
+ * method on other operating system will have no effect.
+ *
+ * @param activate whether rescaling shall be activated or deactivated
+ * @since 3.127
+ */
+public void setRescalingAtRuntime(boolean activate) {
+ // not implemented for GTK
+}
+
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontProvider.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontProvider.java
index 40de9888d40..57fcae13c88 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontProvider.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/SWTFontProvider.java
@@ -16,6 +16,7 @@
import java.util.*;
import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.widgets.*;
/**
* This internal class is used to provide and cache fonts scaled for different zoom levels in the win32
@@ -47,7 +48,7 @@ public static void disposeFontRegistry(Device device) {
}
private static SWTFontRegistry newFontRegistry(Device device) {
- if (DPIUtil.isAutoScaleOnRuntimeActive()) {
+ if (device instanceof Display display && display.isRescalingAtRuntime()) {
return new ScalingSWTFontRegistry(device);
}
return new DefaultSWTFontRegistry(device);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java
index e1929675a72..9c1f6c9e5c1 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java
@@ -4910,13 +4910,13 @@ LRESULT WM_DPICHANGED (long wParam, long lParam) {
event.detail = newNativeZoom;
event.doit = true;
- if (DPIUtil.isAutoScaleOnRuntimeActive()) {
+ if (getDisplay().isRescalingAtRuntime()) {
DPIUtil.setDeviceZoom (newNativeZoom);
}
notifyListeners(SWT.ZoomChanged, event);
- if (DPIUtil.isAutoScaleOnRuntimeActive()) {
+ if (getDisplay().isRescalingAtRuntime()) {
RECT rect = new RECT ();
COM.MoveMemory(rect, lParam, RECT.sizeof);
this.setBoundsInPixels(rect.left, rect.top, rect.right - rect.left, rect.bottom-rect.top);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java
index 72f3b585875..13c0e43ffae 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java
@@ -138,6 +138,7 @@ public class Display extends Device implements Executor {
EventTable eventTable, filterTable;
boolean useOwnDC;
boolean externalEventLoop; // events are dispatched outside SWT, e.g. TrackPopupMenu or DoDragDrop
+ private boolean rescalingAtRuntime;
/* Widget Table */
private Map
+ * Note: This functionality is only available on Windows. Calling this
+ * method on other operating system will always return false.
+ *
+ * @since 3.127
+ */
+public boolean isRescalingAtRuntime() {
+ return rescalingAtRuntime;
+}
+
+/**
+ * Activates or deactivates rescaling of shells at runtime whenever the DPI
+ * scaling of the shell's monitor changes. This is only safe to call as long as
+ * no shell has been created for this display. When changing the value after a
+ * shell has been created for this display, the effect is undefined.
+ *
+ * Note: This functionality is only available on Windows. Calling this
+ * method on other operating system will have no effect.
+ *
+ * @param activate whether rescaling shall be activated or deactivated
+ * @since 3.127
+ */
+public void setRescalingAtRuntime(boolean activate) {
+ rescalingAtRuntime = activate;
+ // dispose a existing font registry for the default display
+ SWTFontProvider.disposeFontRegistry(this);
+ setProperDPIAwareness();
+}
+
+private void setProperDPIAwareness() {
+ long desiredDpiAwareness = OS.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
+ if (OS.WIN32_BUILD < OS.WIN32_BUILD_WIN10_1607) {
+ System.err.println("***WARNING: the OS version does not support setting DPI awareness.");
+ return;
+ }
+ if (rescalingAtRuntime) {
+ desiredDpiAwareness = OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
+ // Auto scaling on runtime requires DPI awareness mode "Per Monitor V2"
+ boolean perMonitorV2Available = OS.WIN32_BUILD >= OS.WIN32_BUILD_WIN10_1809;
+ if (!perMonitorV2Available) {
+ System.err.println(
+ "***WARNING: rescaling at runtime is activated but the OS version does not support required DPI awareness mode PerMonitorV2.");
+ return;
+ }
+ }
+ if (desiredDpiAwareness == OS.GetThreadDpiAwarenessContext()) {
+ return;
+ }
+ long setDpiAwarenessResult = OS.SetThreadDpiAwarenessContext(desiredDpiAwareness);
+ if (setDpiAwarenessResult == 0L) {
+ System.err.println("***WARNING: setting DPI awareness failed.");
+ }
+}
+
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java
index 88bef96ac58..64bd00650d0 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java
@@ -313,7 +313,7 @@ public Shell (Display display, int style) {
createWidget ();
- if (DPIUtil.isAutoScaleOnRuntimeActive()) {
+ if (getDisplay().isRescalingAtRuntime()) {
addListener(SWT.ZoomChanged, this::handleZoomEvent);
}
}