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 controlByHandle; @@ -582,28 +583,8 @@ public Display () { */ public Display (DeviceData data) { super (data); - initializeProperDPIAwareness(); -} - -private void initializeProperDPIAwareness() { - if (!DPIUtil.isAutoScaleOnRuntimeActive()) { - return; - } - // 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; - } - - boolean alreadyUsesPerMonitorV2 = OS.GetThreadDpiAwarenessContext() == OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2; - if (alreadyUsesPerMonitorV2) { - return; - } - long setDpiAwarenessResult = OS.SetThreadDpiAwarenessContext(OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); - if (setDpiAwarenessResult == 0L) { - System.err.println("***WARNING: setting DPI awareness to PerMonitorV2 failed."); + if (DPIUtil.isAutoScaleOnRuntimeActive()) { + setRescalingAtRuntime(true); } } @@ -5267,4 +5248,62 @@ static String withCrLf (String string) { 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 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); } }