Skip to content

Commit

Permalink
Only consider rescaling at runtime enabled when DPI awareness mode fits
Browse files Browse the repository at this point in the history
Activating rescaling at runtime requires a proper DPI awareness mode to
be set. Currently, if setting the DPI awareness mode fails, rescaling
may still be activated if the user requested to. With this change,
setting the rescaling mode of a Display ensures that the correct DPI
awareness for the UI thread is set and, in case an error occurs, the
rescaling mode is not changed. It also adapts some faulty constants and
provides according test cases for setting the rescaling behavior.
  • Loading branch information
HeikoKlare committed Jul 24, 2024
1 parent fc0098c commit 1a5d396
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,8 @@ public class OS extends C {
public static final short DMDUP_SIMPLEX = 1;
public static final short DMDUP_VERTICAL = 2;
public static final short DMDUP_HORIZONTAL = 3;
public static final int DPI_AWARENESS_CONTEXT_UNAWARE = 16;
public static final int DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = 17;
public static final int DPI_AWARENESS_CONTEXT_UNAWARE = 24592;
public static final int DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = 24593;
public static final int DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = 18;
public static final int DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = 34;
public static final int DSTINVERT = 0x550009;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.eclipse.swt.widgets;

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

import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.win32.*;
import org.junit.jupiter.api.*;

public class DisplayWin32Test {

private Display display;

@BeforeAll
public static void assumeIsFittingPlatform() {
PlatformSpecificExecution.assumeIsFittingPlatform();
}

@BeforeEach
public void createDisplay() {
display = new Display();
}

@AfterEach
public void destroyDisplay() {
display.dispose();
}

@Test
public void setRescaleAtRuntime_activate() {
display.setRescalingAtRuntime(true);
assertTrue(display.isRescalingAtRuntime());
assertEquals(OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, OS.GetThreadDpiAwarenessContext());
}

@Test
public void setRescaleAtRuntime_deactivate() {
display.setRescalingAtRuntime(false);
assertFalse(display.isRescalingAtRuntime());
assertEquals(OS.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE, OS.GetThreadDpiAwarenessContext());
}

@Test
public void setRescaleAtRuntime_toggling() {
display.setRescalingAtRuntime(false);
assertFalse(display.isRescalingAtRuntime());
assertEquals(OS.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE, OS.GetThreadDpiAwarenessContext());
display.setRescalingAtRuntime(true);
assertTrue(display.isRescalingAtRuntime());
assertEquals(OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, OS.GetThreadDpiAwarenessContext());
display.setRescalingAtRuntime(false);
assertFalse(display.isRescalingAtRuntime());
assertEquals(OS.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE, OS.GetThreadDpiAwarenessContext());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6856,9 +6856,10 @@ public boolean isRescalingAtRuntime() {
* method on other operating system will have no effect.
*
* @param activate whether rescaling shall be activated or deactivated
* @return whether activating or deactivating the rescaling was successful
* @since 3.127
*/
public void setRescalingAtRuntime(boolean activate) {
public boolean setRescalingAtRuntime(boolean activate) {
// not implemented for Cocoa
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6290,9 +6290,10 @@ public boolean isRescalingAtRuntime() {
* method on other operating system will have no effect.
*
* @param activate whether rescaling shall be activated or deactivated
* @return whether activating or deactivating the rescaling was successful
* @since 3.127
*/
public void setRescalingAtRuntime(boolean activate) {
public boolean setRescalingAtRuntime(boolean activate) {
// not implemented for GTK
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5272,38 +5272,42 @@ public boolean isRescalingAtRuntime() {
* method on other operating system will have no effect.
*
* @param activate whether rescaling shall be activated or deactivated
* @return whether activating or deactivating the rescaling was successful
* @since 3.127
*/
public void setRescalingAtRuntime(boolean activate) {
rescalingAtRuntime = activate;
// dispose a existing font registry for the default display
SWTFontProvider.disposeFontRegistry(this);
setProperDPIAwareness();
public boolean setRescalingAtRuntime(boolean activate) {
int desiredApiAwareness = activate ? OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 : OS.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
if (setDPIAwareness(desiredApiAwareness)) {
rescalingAtRuntime = activate;
// dispose a existing font registry for the default display
SWTFontProvider.disposeFontRegistry(this);
return true;
}
return false;
}

private void setProperDPIAwareness() {
long desiredDpiAwareness = OS.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
private boolean setDPIAwareness(int desiredDpiAwareness) {
if (OS.WIN32_BUILD < OS.WIN32_BUILD_WIN10_1607) {
System.err.println("***WARNING: the OS version does not support setting DPI awareness.");
return;
return false;
}
if (rescalingAtRuntime) {
desiredDpiAwareness = OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
// Auto scaling on runtime requires DPI awareness mode "Per Monitor V2"
if (desiredDpiAwareness == OS.GetThreadDpiAwarenessContext()) {
return true;
}
if (desiredDpiAwareness == OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) {
// "Per Monitor V2" only available in more recent Windows version
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;
System.err.println("***WARNING: the OS version does not support DPI awareness mode PerMonitorV2.");
return false;
}
}
if (desiredDpiAwareness == OS.GetThreadDpiAwarenessContext()) {
return;
}
long setDpiAwarenessResult = OS.SetThreadDpiAwarenessContext(desiredDpiAwareness);
if (setDpiAwarenessResult == 0L) {
System.err.println("***WARNING: setting DPI awareness failed.");
return false;
}
return true;
}

}

0 comments on commit 1a5d396

Please sign in to comment.