summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-01-31 22:57:23 +0100
committerSven Gothel <[email protected]>2023-01-31 22:57:23 +0100
commit7982cc52344c025c40da45fd4b946056a63bc855 (patch)
tree821c49296827111efc7b4b207ae4cc2726320559
parentad38d1559854985b1131e5b6c7274a392b5bc265 (diff)
NEWT Soft-PixelScale (p7): get{Global->}PixelScaleEnv(..): Support per monitor values w/ QT_SCREEN_SCALE_FACTORS syntax, use for X11v2.4.0
Per-monitor values are parsed if value is not a float and stored in a given Map<String,float[2]>, parallel to a detected global_pixel_scale_xy. The per-monitor value syntax matches QT_SCREEN_SCALE_FACTORS, i.e. the regular expression '(<string>=<float>;)+', e.g. QT_SCREEN_SCALE_FACTORS='DP-1=1.25;DP-2=1.25;HDMI-1=1.25;' The per-monitor value is preferred and on X11 stored within the MonitorDevice, matching the MonitorDevice's name. The following env-var names are searched on X11: "QT_SCREEN_SCALE_FACTORS", "QT_SCALE_FACTOR", "GDK_SCALE", "SOFT_SCALE"
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java100
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java30
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java5
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java6
4 files changed, 113 insertions, 28 deletions
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
index c732151e5..8f45001f9 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
@@ -228,42 +228,106 @@ public class SurfaceScaleUtils {
}
/**
+ * Returns a proper string representation of the monitor-name to float[2] pixel-scale map.
+ */
+ public static String toString(final Map<String,float[/*2*/]> monitorNameToScale) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("{ ");
+ for(final String name: monitorNameToScale.keySet()) {
+ sb.append("'").append(name).append("'").append(" = ( ");
+ final float[] value = monitorNameToScale.get(name);
+ if( null != value && 2 == value.length ) {
+ sb.append(value[0]).append(" / ").append(value[1]);
+ }
+ sb.append(" ), ");
+ }
+ sb.append(" }");
+ return sb.toString();
+ }
+
+ /**
* Get global pixel-scale values from environment variables, e.g.:
+ * - QT_SCREEN_SCALE_FACTORS
* - QT_SCALE_FACTOR
* - GDK_SCALE
* See https://wiki.archlinux.org/title/HiDPI
* @param env_var_names array of potential environment variable names, treated as float.
- * @param pixel_scale_xy store for resulting scale factors
- * @return index of first found variable name within env_var_names, otherwise -1
+ * @param global_pixel_scale_xy store for resulting scale factors
+ * @param monitorNameToScale storage mapping monitor names to their pixel_scale_xy, if variable value is of regular expression '(<string>=<float>;)+',
+ * i.e. QT_SCREEN_SCALE_FACTORS='DP-1=1.25;DP-2=1.25;HDMI-1=1.25;'
+ * @return index of first found global variable name within env_var_names, otherwise -1
*/
- public static int getGlobalPixelScaleEnv(final String[] env_var_names, final float[] pixel_scale_xy) {
+ public static int getPixelScaleEnv(final String[] env_var_names, final float[] global_pixel_scale_xy, final Map<String,float[/*2*/]> monitorNameToScale) {
final Map<String, String> env = SecurityUtil.doPrivileged(new PrivilegedAction<Map<String, String>>() {
@Override
public Map<String, String> run() {
return System.getenv();
}
});
- float value = -1.0f;
+ float global_value = -1.0f;
+ int global_idx = -1;
+ int mapping_idx = -1;
boolean done = false;
- int var_idx = 0;
- while( var_idx < env_var_names.length && !done ) {
+ for(int var_idx = 0; var_idx < env_var_names.length && !done; ++var_idx ) {
final String env_var_name = env_var_names[var_idx];
final String s_value = env.get(env_var_name);
- if( null != s_value ) {
- try {
- value = Float.valueOf(s_value);
- done = true;
- } catch(final NumberFormatException nfe) {
- ++var_idx;
+ if( null == s_value || s_value.isEmpty()) {
+ continue; // next
+ }
+ try {
+ final float v = Float.valueOf(s_value);
+ if( 0 > global_idx ) { // no overwrite
+ global_value = v;
+ global_idx = var_idx;
+ }
+ } catch(final NumberFormatException nfe) {
+ if( 0 <= mapping_idx ) {
+ continue;
+ }
+ // Attempt to parse regular expression '(<string>=<float>;)+',
+ // i.e. QT_SCREEN_SCALE_FACTORS='DP-1=1.25;DP-2=1.25;HDMI-1=1.25;'
+ final String[] pairs = s_value.split(";");
+ if( null != pairs ) {
+ for(final String pair : pairs) {
+ if( null == pair || pair.isEmpty() ) {
+ continue; // empty is OK, next
+ }
+ final String[] elems = pair.split("=");
+ if( null == elems || 2 != elems.length ) {
+ // syntax error, bail out
+ monitorNameToScale.clear();
+ break;
+ }
+ if( null == elems[0] || elems[0].isEmpty() ) {
+ // syntax error (empty name), bail out
+ monitorNameToScale.clear();
+ break;
+ }
+ if( null == elems[1] || elems[1].isEmpty() ) {
+ // syntax error (empty value), bail out
+ monitorNameToScale.clear();
+ break;
+ }
+ try {
+ final float pair_value = Float.valueOf(elems[1]);
+ monitorNameToScale.put(elems[0], new float[] { pair_value, pair_value} );
+ mapping_idx = var_idx;
+ } catch(final NumberFormatException nfe2) {
+ // syntax error, bail out
+ monitorNameToScale.clear();
+ break;
+ }
+ }
}
- } else {
- ++var_idx;
}
+ done = 0 <= mapping_idx && 0 <= global_idx;
}
- if( done ) {
- pixel_scale_xy[0] = value;
- pixel_scale_xy[1] = value;
- return var_idx;
+ if( 0 <= global_idx ) {
+ global_pixel_scale_xy[0] = global_value;
+ global_pixel_scale_xy[1] = global_value;
+ return global_idx;
+ } else if( 0 <= mapping_idx ) {
+ return mapping_idx;
} else {
return -1;
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
index 1ffa26407..83929afe3 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
@@ -34,7 +34,9 @@
package jogamp.newt.driver.x11;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import com.jogamp.nativewindow.AbstractGraphicsDevice;
import com.jogamp.nativewindow.ScalableSurface;
@@ -60,24 +62,33 @@ import com.jogamp.newt.MonitorMode;
public class ScreenDriver extends ScreenImpl {
protected static final boolean DEBUG_TEST_RANDR13_DISABLED;
protected static final float[] global_pixel_scale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+ protected static final Map<String,float[/*2*/]> monitor_pixel_scale_map = new HashMap<String, float[]>();
protected static final boolean global_pixel_scale_set;
+ protected static final boolean monitor_pixel_scale_map_set;
static {
Debug.initSingleton();
DEBUG_TEST_RANDR13_DISABLED = PropertyAccess.isPropertyDefined("newt.test.Screen.disableRandR13", true);
- final String[] env_var_names = new String[] { "GDK_SCALE", "QT_SCALE_FACTOR", "SOFT_SCALE" };
+ final String[] env_var_names = new String[] { "QT_SCREEN_SCALE_FACTORS", "QT_SCALE_FACTOR", "GDK_SCALE", "SOFT_SCALE" };
int var_name_idx = -1;
try {
- var_name_idx = SurfaceScaleUtils.getGlobalPixelScaleEnv(env_var_names, global_pixel_scale);
+ var_name_idx = SurfaceScaleUtils.getPixelScaleEnv(env_var_names, global_pixel_scale, monitor_pixel_scale_map);
} catch (final Throwable t) { t.printStackTrace(); }
if( 0 <= var_name_idx && var_name_idx < env_var_names.length ) {
- global_pixel_scale_set = true;
+ global_pixel_scale_set = global_pixel_scale[0] != ScalableSurface.AUTOMAX_PIXELSCALE && global_pixel_scale[1] != ScalableSurface.AUTOMAX_PIXELSCALE;
+ monitor_pixel_scale_map_set = !monitor_pixel_scale_map.isEmpty();
if( DEBUG ) {
- System.err.println("X11Screen: Global PixelScale Set: "+env_var_names[var_name_idx]+": "+global_pixel_scale[0]+"/"+global_pixel_scale[1]);
+ System.err.println("X11Screen: Env PixelScale: Env-Variable "+env_var_names[var_name_idx]);
+ System.err.println("X11Screen: Env PixelScale: Global: Set "+global_pixel_scale_set+", "+global_pixel_scale[0]+"/"+global_pixel_scale[1]);
+ System.err.println("X11Screen: Env PixelScale: Map: Set "+monitor_pixel_scale_map_set+", "+SurfaceScaleUtils.toString(monitor_pixel_scale_map));
}
} else {
+ if( DEBUG ) {
+ System.err.println("X11Screen: Env PixelScale: None");
+ }
global_pixel_scale_set = false;
+ monitor_pixel_scale_map_set = false;
}
DisplayDriver.initSingleton();
@@ -138,10 +149,6 @@ public class ScreenDriver extends ScreenImpl {
try {
if( rAndR.beginInitialQuery(device.getHandle(), this) ) {
try {
- final float pixel_scale[] = { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
- if( global_pixel_scale_set ) {
- System.arraycopy(global_pixel_scale, 0, pixel_scale, 0, 2);
- }
final int[] crt_ids = rAndR.getMonitorDeviceIds(device.getHandle(), this);
final int crtCount = null != crt_ids ? crt_ids.length : 0;
@@ -178,6 +185,13 @@ public class ScreenDriver extends ScreenImpl {
if( null != monitorProps &&
MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps[0] && // Enabled ? I.e. contains active modes ?
MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES <= monitorProps.length ) {
+ float pixel_scale[] = null;
+ if( monitor_pixel_scale_map_set && null != monitorName && !monitorName.isEmpty() ) {
+ pixel_scale = monitor_pixel_scale_map.get(monitorName);
+ }
+ if( null == pixel_scale && global_pixel_scale_set ) {
+ pixel_scale = global_pixel_scale;
+ }
MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, monitorName, pixel_scale,
true /* invscale_wuviewport */, monitorProps, 0, null);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index 28f881bab..5fb01c619 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -108,6 +108,11 @@ public class WindowDriver extends WindowImpl {
if( null != md ) {
final float newPixelScale[] = { 0, 0 };
md.getPixelScale(newPixelScale);
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("Window.updatePixelScaleByMonitor: pixel "+getSurfaceBounds()+", window "+getBounds());
+ System.err.println("Window.updatePixelScaleByMonitor: monitor "+md);
+ System.err.println("Window.updatePixelScaleByMonitor: has "+hasPixelScale[0]+", new "+newPixelScale[0]+" - "+getThreadName());
+ }
res = applySoftPixelScale(move_diff, sendEvent, defer, newPixelScale);
}
return res;
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java
index 78f59931a..a001383b8 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java
@@ -110,20 +110,22 @@ public class TestScreenMode00aNEWT extends UITestCase {
final long monitor_handle = -1;
final int monitor_id = -1;
+ final String monitor_name = "DP-1";
final DimensionImmutable sizeMM = new Dimension(50, 50);
final Rectangle viewport = new Rectangle(0, 0, 1920, 1080);
final ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>(false, ArrayHashSet.DEFAULT_INITIAL_CAPACITY, ArrayHashSet.DEFAULT_LOAD_FACTOR);
supportedModes.add(modeOut);
- final MonitorDevice monOut = new MonitorDeviceImpl(null, monitor_handle, monitor_id, false, true, sizeMM, modeOut, null, viewport, viewport, supportedModes);
+ final MonitorDevice monOut = new MonitorDeviceImpl(null, monitor_handle, monitor_id, monitor_name, false, true, sizeMM, modeOut, null, viewport, viewport, supportedModes);
System.err.println("01 out : "+monOut);
cache.monitorDevices.add(monOut);
{
final int[] props = MonitorModeProps.streamOutMonitorDevice(monOut);
- final MonitorDevice monIn = MonitorModeProps.streamInMonitorDevice(cache, null, monitor_handle, null, false /* invscale_wuviewport */, props, 0, null);
+ final MonitorDevice monIn = MonitorModeProps.streamInMonitorDevice(cache, null, monitor_handle, monitor_name, null, false /* invscale_wuviewport */, props, 0, null);
System.err.println("01 in : "+monIn);
Assert.assertEquals(monOut.getHandle(), monIn.getHandle());
Assert.assertEquals(monOut.getId(), monIn.getId());
+ Assert.assertEquals(monOut.getName(), monIn.getName());
Assert.assertEquals(monOut.isClone(), monIn.isClone());
Assert.assertEquals(monOut.isPrimary(), monIn.isPrimary());
Assert.assertEquals(monOut.getViewport(), monIn.getViewport());