aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/classes/jogamp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-01-31 07:35:58 +0100
committerSven Gothel <[email protected]>2023-01-31 07:35:58 +0100
commit97b79ad351e48e7d3c6f9c95bacdf4f9d5d158ef (patch)
tree0945989bcd6ffbe87f295f422002b3055a1e082d /src/newt/classes/jogamp
parent6eb13066996e94b2fe40bf64e74ea43d8f4e9171 (diff)
NEWT Soft-PixelScale (p6): Implement Soft-PixelScale for X11 and Windows ... (working state)
Both: - Using Soft-PixelScale mode, i.e. converting all given window-units to pixel-units for native GDI/X11 ops - Using scaled pixel-sized surface - Adjusting NEWT's Monitor's window-unit viewport value to pixel-scale For X11: - Using global scale factor from environment variable, either: "GDK_SCALE", "QT_SCALE_FACTOR" or "SOFT_SCALE". The latter is for testing only. See https://wiki.archlinux.org/title/HiDPI For Windows: - Using actual monitor's pixel-scale via native SHC API (Shellscaling API, shcore.dll) Misc: - SurfaceScaleUtils.getGlobalPixelScaleEnv() reads a float value from given env names, first come, first serve - MonitorModeProps.streamInMonitorDevice(..): Add `invscale_wuviewport` argument to scale wuvieport for soft-pixel-scale - TestGearsNEWT: Enhance GL2 demo to be suitable for manual tests, this since my Windows KVM machine doesn't support ES2 - TestGLContextDrawableSwitch10NEWT: Add a few more test constraints .. working Tested: - Manually on a Windows virtual machine (KVM) using - 2 virtualized 'Video QXL' cards and - and 'remote-viewer' to see the 2 monitors since `Virtual Machine Manager` build-in doesn't support - remote-viewer spice://localhost:5917 - Manually on a Linux machine w/ SOFT_SCALE - Both, X11 and Windows - Place window on each monitor - Move window across monitors w/ pixel-scale change (or not) - TODO: Test and fix utilization with AWT, i.e. NewtCanvasAWT
Diffstat (limited to 'src/newt/classes/jogamp')
-rw-r--r--src/newt/classes/jogamp/newt/MonitorModeProps.java18
-rw-r--r--src/newt/classes/jogamp/newt/ScreenImpl.java6
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java5
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/egl/gbm/ScreenDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java3
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java3
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java4
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java123
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java26
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java101
16 files changed, 251 insertions, 52 deletions
diff --git a/src/newt/classes/jogamp/newt/MonitorModeProps.java b/src/newt/classes/jogamp/newt/MonitorModeProps.java
index 873ee3ed6..292551559 100644
--- a/src/newt/classes/jogamp/newt/MonitorModeProps.java
+++ b/src/newt/classes/jogamp/newt/MonitorModeProps.java
@@ -273,6 +273,7 @@ public class MonitorModeProps {
* @param screen the associated {@link ScreenImpl}
* @param monitor_handle unique monitor long handle, implementation specific
* @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}.
+ * @param invscale_wuviewport if true, the viewport in window-units will be scaled by 1/pixelScale for soft-pixel-scale
* @param monitorProperties the input data inclusive supported modes.
* @param offset the offset to the input data
* @param monitor_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
@@ -281,8 +282,8 @@ public class MonitorModeProps {
*/
public static MonitorDevice streamInMonitorDevice(final Cache cache, final ScreenImpl screen,
final long monitor_handle,
- final float[] pixelScale, final int[] monitorProperties,
- int offset, final int[] monitor_idx) {
+ final float[] pixelScale, final boolean invscale_wuviewport,
+ final int[] monitorProperties, int offset, final int[] monitor_idx) {
// min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
final int count = monitorProperties[offset];
if(MIN_MONITOR_DEVICE_PROPERTIES > count) {
@@ -303,6 +304,9 @@ public class MonitorModeProps {
final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES;
final Rectangle viewportPU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
final Rectangle viewportWU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+ if( invscale_wuviewport && null != pixelScale ) {
+ viewportWU.scaleInv(pixelScale[0], pixelScale[1]);
+ }
final MonitorMode currentMode;
{
final int modeId = monitorProperties[offset++];
@@ -360,6 +364,7 @@ public class MonitorModeProps {
* @param monitor_handle unique monitor long handle, implementation specific
* @param currentMode pre-fetched current {@link MonitorMode}s from cache.
* @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}.
+ * @param invscale_wuviewport if true, the viewport in window-units will be scaled by 1/pixelScale for soft-pixel-scale
* @param supportedModes pre-assembled list of supported {@link MonitorMode}s from cache.
* @param monitorProperties the input data minus supported modes!
* @param offset the offset to the input data
@@ -371,9 +376,9 @@ public class MonitorModeProps {
final long monitor_handle,
final MonitorMode currentMode,
final float[] pixelScale,
- final ArrayHashSet<MonitorMode> supportedModes,
- final int[] monitorProperties, int offset,
- final int[] monitor_idx) {
+ final boolean invscale_wuviewport,
+ final ArrayHashSet<MonitorMode> supportedModes, final int[] monitorProperties,
+ int offset, final int[] monitor_idx) {
// min 11: count, id, ScreenSizeMM[width, height], Viewport[x, y, width, height], currentMonitorModeId, rotation, supportedModeId+
final int count = monitorProperties[offset];
if(MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES != count) {
@@ -392,6 +397,9 @@ public class MonitorModeProps {
final DimensionImmutable sizeMM = streamInResolution(monitorProperties, offset); offset+=NUM_RESOLUTION_PROPERTIES;
final Rectangle viewportPU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
final Rectangle viewportWU = new Rectangle(monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++], monitorProperties[offset++]);
+ if( invscale_wuviewport && null != pixelScale ) {
+ viewportWU.scaleInv(pixelScale[0], pixelScale[1]);
+ }
MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, monitor_handle, monitor_id, isClone, isPrimary,
sizeMM, currentMode, pixelScale,
viewportPU, viewportWU, supportedModes);
diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java
index 1dba31d4f..d90ee73bb 100644
--- a/src/newt/classes/jogamp/newt/ScreenImpl.java
+++ b/src/newt/classes/jogamp/newt/ScreenImpl.java
@@ -360,8 +360,8 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
* <li>{@link MonitorModeProps#MIN_MONITOR_DEVICE_PROPERTIES}</li>
* </ul>, i.e.
* <ul>
- * <li>{@link MonitorModeProps#streamInMonitorDevice(jogamp.newt.MonitorModeProps.Cache, ScreenImpl, long, double[], int[], int, int[])}</li>
- * <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, long, ArrayHashSet, int[], int, ScreenImpl)}</li>
+ * <li>{@link MonitorModeProps#streamInMonitorDevice(jogamp.newt.MonitorModeProps.Cache, ScreenImpl, long, double[], boolean, int[], int, int[])}</li>
+ * <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, long, ArrayHashSet, boolean, int[], int, ScreenImpl)}</li>
* <li>{@link MonitorModeProps#streamInMonitorMode(int[], jogamp.newt.MonitorModeProps.Cache, int[], int)}</li>
* </ul>
* @param cache memory pool caching the result
@@ -520,7 +520,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
if( MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES != i ) {
throw new InternalError("XX");
}
- return MonitorModeProps.streamInMonitorDevice(cache, this, monitorId, null, props, 0, null);
+ return MonitorModeProps.streamInMonitorDevice(cache, this, monitorId, null, false /* invscale_wuviewport */, props, 0, null);
}
/**
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index ef8c4916d..ae63c4539 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -2966,12 +2966,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
boolean res = false;
if( DEBUG_IMPLEMENTATION ) {
System.err.println("Window.SoftPixelScale.0a: req "+reqPixelScale[0]+", has "+hasPixelScale[0]+", new "+newPixelScale[0]+" - "+getThreadName());
- Thread.dumpStack();
+ // Thread.dumpStack();
}
synchronized( scaleLock ) {
- if( DEBUG_IMPLEMENTATION ) {
- System.err.println("Window.SoftPixelScale.0b: req "+reqPixelScale[0]+", has "+hasPixelScale[0]+", new "+newPixelScale[0]+" - "+getThreadName());
- }
try {
res = applySoftPixelScaleImpl(move_diff, sendEvent, defer, newPixelScale);
} finally {
diff --git a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
index 3c0b1aef4..8d73592b5 100644
--- a/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
@@ -116,7 +116,7 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
props[i++] = 0; // rotated viewport y window-units
props[i++] = outMetrics.widthPixels; // rotated viewport width window-units
props[i++] = outMetrics.heightPixels; // rotated viewport height window-units
- MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, cache.monitorModes, props, 0, null);
+ MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, false, cache.monitorModes, props, 0, null);
}
@Override
diff --git a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
index d577ed501..fc4bf03a4 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
@@ -122,7 +122,7 @@ public class ScreenDriver extends ScreenImpl {
props[i++] = 0; // rotated viewport y window-units
props[i++] = currentMode.getRotatedWidth(); // rotated viewport width window-units
props[i++] = currentMode.getRotatedHeight(); // rotated viewport height window-units
- MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, cache.monitorModes, props, 0, null);
+ MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, false, cache.monitorModes, props, 0, null);
}
@Override
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
index 62dbd0c72..3cdb368f2 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
@@ -97,7 +97,7 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
props[i++] = 0; // rotated viewport y window-units
props[i++] = fixedWidth; // FIXME rotated viewport width window-units
props[i++] = fixedHeight; // FIXME rotated viewport height window-units
- MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, cache.monitorModes, props, 0, null);
+ MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, false, cache.monitorModes, props, 0, null);
}
@Override
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
index 9e05e1002..1b3807a94 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
@@ -90,7 +90,7 @@ public class ScreenDriver extends ScreenImpl {
props[i++] = 0; // rotated viewport y window-units
props[i++] = cachedWidth; // rotated viewport width window-units
props[i++] = cachedHeight; // rotated viewport height window-units
- MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, cache.monitorModes, props, 0, null);
+ MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, false, cache.monitorModes, props, 0, null);
}
@Override
diff --git a/src/newt/classes/jogamp/newt/driver/egl/gbm/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/egl/gbm/ScreenDriver.java
index 5281f0ddc..a08b5a445 100644
--- a/src/newt/classes/jogamp/newt/driver/egl/gbm/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/egl/gbm/ScreenDriver.java
@@ -129,7 +129,7 @@ public class ScreenDriver extends ScreenImpl {
props[i++] = 0; // rotated viewport y window-units
props[i++] = mode[scridx].getHdisplay(); // rotated viewport width window-units
props[i++] = mode[scridx].getVdisplay(); // rotated viewport height window-units
- MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, cache.monitorModes, props, 0, null);
+ MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, false, cache.monitorModes, props, 0, null);
crtc_ids = new int[] { encoder[scridx].getCrtc_id() };
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
index ceb2c4cc6..7eb6eea92 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
@@ -99,7 +99,7 @@ public class ScreenDriver extends jogamp.newt.ScreenImpl {
props[i++] = 0; // rotated viewport y window-units
props[i++] = cachedWidth; // rotated viewport width window-units
props[i++] = cachedWidth; // rotated viewport height window-units
- MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, cache.monitorModes, props, 0, null);
+ MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, false, cache.monitorModes, props, 0, null);
}
@Override
diff --git a/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java
index de5cdd239..4cf459699 100644
--- a/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java
@@ -177,7 +177,8 @@ public class ScreenDriver extends ScreenImpl {
// merge monitor-props + supported modes
final float pixelScale = crtProps.pixelScaleArray[crtIdx];
MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode,
- new float[] { pixelScale, pixelScale }, supportedModes, crtProps.propsFixedArray[crtIdx], 0, null);
+ new float[] { pixelScale, pixelScale }, false /* invscale_wuviewport */,
+ supportedModes, crtProps.propsFixedArray[crtIdx], 0, null);
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
index 3112aa88f..ba28e161d 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
@@ -95,7 +95,7 @@ public class ScreenDriver extends ScreenImpl {
props[i++] = 0; // rotated viewport y window-units
props[i++] = cachedWidth; // rotated viewport width window-units
props[i++] = cachedWidth; // rotated viewport height window-units
- MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, cache.monitorModes, props, 0, null);
+ MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode, null, false, cache.monitorModes, props, 0, null);
}
@Override
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
index a4823034f..635fffc0b 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
@@ -183,7 +183,8 @@ public class ScreenDriver extends ScreenImpl {
// merge monitor-props + supported modes
final float pixelScale = crtProps.pixelScaleArray[crtIdx];
MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, currentMode,
- new float[] { pixelScale, pixelScale }, supportedModes, crtProps.propsFixedArray[crtIdx], 0, null);
+ new float[] { pixelScale, pixelScale }, false /* invscale_wuviewport */,
+ supportedModes, crtProps.propsFixedArray[crtIdx], 0, null);
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
index 002836e0c..c3aa94648 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
@@ -143,7 +143,8 @@ public class ScreenDriver extends ScreenImpl {
monitor_handle = monitor_id;
}
// merge monitor-props + supported modes
- MonitorModeProps.streamInMonitorDevice(cache, this, monitor_handle, currentMode, pixel_scale, supportedModes, monitorProps, 0, null);
+ MonitorModeProps.streamInMonitorDevice(cache, this, monitor_handle, currentMode, pixel_scale, true /* invscale_wuviewport */,
+ supportedModes, monitorProps, 0, null);
// next monitor, 1st mode
supportedModes = new ArrayHashSet<MonitorMode>(false, ArrayHashSet.DEFAULT_INITIAL_CAPACITY, ArrayHashSet.DEFAULT_LOAD_FACTOR);
@@ -168,6 +169,7 @@ public class ScreenDriver extends ScreenImpl {
int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT;
viewportPU.set(monitorProps[offset++], monitorProps[offset++], monitorProps[offset++], monitorProps[offset++]);
viewportWU.set(monitorProps[offset++], monitorProps[offset++], monitorProps[offset++], monitorProps[offset++]);
+ viewportWU.scaleInv(pixelScale[0], pixelScale[1]);
return true;
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
index fb20265ce..1605d4126 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
@@ -36,6 +36,7 @@ package jogamp.newt.driver.windows;
import java.nio.ByteBuffer;
+import jogamp.nativewindow.SurfaceScaleUtils;
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.GDIUtil;
import jogamp.newt.PointerIconImpl;
@@ -47,11 +48,12 @@ import com.jogamp.nativewindow.NativeWindowException;
import com.jogamp.nativewindow.VisualIDHolder;
import com.jogamp.nativewindow.util.InsetsImmutable;
import com.jogamp.nativewindow.util.Point;
-
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionNumber;
+import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.MonitorEvent;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseEvent.PointerType;
@@ -61,7 +63,7 @@ public class WindowDriver extends WindowImpl {
DisplayDriver.initSingleton();
}
- private long hmon;
+ private volatile long hmon;
private long hdc;
private long hdc_old;
private long windowHandleClose;
@@ -69,6 +71,20 @@ public class WindowDriver extends WindowImpl {
public WindowDriver() {
}
+ /**
+ * Essentially updates {@code hasPixelScale}
+ */
+ private boolean updatePixelScaleByMonitor(final long crt_handle, final int[] move_diff, final boolean sendEvent, final boolean defer) {
+ boolean res = false;
+ if( 0 != crt_handle ) {
+ final float newPixelScaleRaw[] = { 0, 0 };
+ if( GDIUtil.GetMonitorPixelScale(crt_handle, newPixelScaleRaw) ) {
+ res = applySoftPixelScale(move_diff, sendEvent, defer, newPixelScaleRaw);
+ }
+ }
+ return res;
+ }
+
@Override
protected int lockSurfaceImpl() {
if (0 != hdc) {
@@ -81,7 +97,14 @@ public class WindowDriver extends WindowImpl {
if( 0 == hdc ) {
return LOCK_SURFACE_NOT_READY;
}
- hmon = MonitorFromWindow0(hWnd);
+ if(DEBUG_IMPLEMENTATION) {
+ final long _hmon = GDIUtil.GetMonitorFromWindow(hWnd);
+ if (hmon != _hmon) {
+ System.err.println("Info: Window Device Changed (L) "+getThreadName()+
+ ", HMON "+toHexString(hmon)+" -> "+toHexString(_hmon));
+ // Thread.dumpStack();
+ }
+ }
// Let's not trigger on HDC change, GLDrawableImpl.'s destroy/create is a nop here anyways.
// FIXME: Validate against EGL surface creation: ANGLE uses HWND -> fine!
@@ -113,20 +136,27 @@ public class WindowDriver extends WindowImpl {
}
@Override
- public boolean hasDeviceChanged() {
- if(0!=getWindowHandle()) {
- final long _hmon = MonitorFromWindow0(getWindowHandle());
- if (hmon != _hmon) {
- if(DEBUG_IMPLEMENTATION) {
- System.err.println("Info: Window Device Changed "+Thread.currentThread().getName()+
- ", HMON "+toHexString(hmon)+" -> "+toHexString(_hmon));
- // Thread.dumpStack();
- }
- hmon = _hmon;
- return true;
- }
+ protected void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ if( hmon == me.getMonitor().getHandle() ) {
+ updatePixelScaleByMonitor(me.getMonitor().getHandle(), null, false /* sendEvent*/, false /* defer */); // send reshape event itself
}
- return false;
+ }
+
+ @Override
+ public final boolean setSurfaceScale(final float[] pixelScale) {
+ super.setSurfaceScale(pixelScale); // pixelScale -> reqPixelScale
+
+ boolean changed = false;
+ if( isNativeValid() ) {
+ changed = applySoftPixelScale(null, true /* sendEvent */, false /* defer */, reqPixelScale);
+ }
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.setPixelScale: min["+minPixelScale[0]+", "+minPixelScale[1]+"], max["+
+ maxPixelScale[0]+", "+maxPixelScale[1]+"], req["+
+ reqPixelScale[0]+", "+reqPixelScale[1]+"] -> result["+
+ hasPixelScale[0]+", "+hasPixelScale[1]+"] - changed "+changed+", realized "+isNativeValid());
+ }
+ return changed;
}
@Override
@@ -150,10 +180,14 @@ public class WindowDriver extends WindowImpl {
flags |= CHANGE_MASK_MAXIMIZED_VERT;
maxCount++;
}
+ final int[] xy_pix = getPixelPosI();
+ final int[] sz_pix = getPixelSizeI();
+
+ // this.convertToWindowUnits(null)
final long _windowHandle = CreateWindow0(DisplayDriver.getHInstance(), display.getWindowClassName(), display.getWindowClassName(),
winVer.getMajor(), winVer.getMinor(),
getParentWindowHandle(),
- getX(), getY(), getWidth(), getHeight(), flags);
+ xy_pix[0], xy_pix[1], sz_pix[0], sz_pix[1], flags);
if ( 0 == _windowHandle ) {
throw new NativeWindowException("Error creating window");
}
@@ -164,10 +198,17 @@ public class WindowDriver extends WindowImpl {
setWindowHandle(_windowHandle);
windowHandleClose = _windowHandle;
- if( 0 == ( STATE_MASK_CHILDWIN & flags ) && 1 == maxCount ) {
- reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), flags);
+ if( 0 == ( STATE_MASK_CHILDWIN & flags ) && 1 <= maxCount ) {
+ reconfigureWindowImpl(xy_pix[0], xy_pix[1], sz_pix[0], sz_pix[1], flags);
}
+ hmon = GDIUtil.GetMonitorFromWindow(_windowHandle);
+ boolean changedPixelScale = applySoftPixelScale(null, true /* sendEvent */, false /* defer */, reqPixelScale);
+ if( !changedPixelScale ) {
+ changedPixelScale = updatePixelScaleByMonitor(hmon, null, true /* sendEvent */, false /* defer */);
+ }
+ positionModified[0] = changedPixelScale;
+
if(DEBUG_IMPLEMENTATION) {
final Exception e = new Exception("Info: Window new window handle "+Thread.currentThread().getName()+
" (Parent HWND "+toHexString(getParentWindowHandle())+
@@ -201,6 +242,7 @@ public class WindowDriver extends WindowImpl {
windowHandleClose = 0;
hdc = 0;
hdc_old = 0;
+ hmon = 0;
}
@Override
@@ -244,7 +286,11 @@ public class WindowDriver extends WindowImpl {
if( changeDecoration && isTranslucent ) {
GDIUtil.DwmSetupTranslucency(getWindowHandle(), false);
}
- reconfigureWindow0( getParentWindowHandle(), getWindowHandle(), x, y, width, height, flags);
+ final int xy_pix[] = SurfaceScaleUtils.scale(new int[2], x, y, hasPixelScale);
+ final int sz_pix[] = SurfaceScaleUtils.scale(new int[2], width, height, hasPixelScale);
+ reconfigureWindow0( getParentWindowHandle(), getWindowHandle(),
+ xy_pix[0], xy_pix[1], sz_pix[0], sz_pix[1], flags);
+
if( changeDecoration && isTranslucent ) {
GDIUtil.DwmSetupTranslucency(getWindowHandle(), true);
}
@@ -259,6 +305,37 @@ public class WindowDriver extends WindowImpl {
}
@Override
+ protected boolean positionChanged(final boolean defer, final boolean windowUnits, final int newX, final int newY) {
+ final boolean res = super.positionChanged(defer, windowUnits, newX, newY);
+
+ if ( res ) {
+ final long hWnd = getWindowHandle();
+ if( 0 != hWnd ) {
+ final long _hmon = GDIUtil.GetMonitorFromWindow(hWnd);
+ if( hmon != _hmon ) {
+ final int[] move_diff = new int[] { 0, 0 };
+ MonitorDevice.Orientation orientation = MonitorDevice.Orientation.clone;
+ // Move from md0 -> md1
+ final MonitorDevice md0 = getScreen().getMonitorByHandle(hmon);
+ final MonitorDevice md1 = getScreen().getMonitorByHandle(_hmon);
+ if( null != md0 && null != md1 ) {
+ orientation = md1.getOrientationTo(md0, move_diff);
+ }
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Info: Window Device Changed (P: "+newX+"/"+newY+
+ ", crt_move[orient "+orientation+", diff "+move_diff[0]+"/"+move_diff[1]+") "+
+ ", HMON "+toHexString(hmon)+" -> "+toHexString(_hmon)+
+ " - "+Thread.currentThread().getName());
+ }
+ hmon = _hmon;
+ updatePixelScaleByMonitor(_hmon, move_diff, true /* sendEvent */, defer);
+ }
+ }
+ }
+ return res;
+ }
+
+ @Override
protected void requestFocusImpl(final boolean force) {
requestFocus0(getWindowHandle(), force);
}
@@ -307,7 +384,8 @@ public class WindowDriver extends WindowImpl {
this.runOnEDTIfAvail(true, new Runnable() {
@Override
public void run() {
- final Point sPos = convertToPixelUnits( getLocationOnScreenImpl(x, y) );
+ // shortcut from getLocationOnScreenImpl(..) while maintaining pixel-units
+ final Point sPos = GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y );
warpPointer0(getWindowHandle(), sPos.getX(), sPos.getY());
}
});
@@ -316,7 +394,8 @@ public class WindowDriver extends WindowImpl {
@Override
protected Point getLocationOnScreenImpl(final int x, final int y) {
- return GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, x, y);
+ final int xy_pix[] = SurfaceScaleUtils.scale(new int[2], x, y, hasPixelScale);
+ return convertToWindowUnits( GDIUtil.GetRelativeLocation( getWindowHandle(), 0 /*root win*/, xy_pix[0], xy_pix[1]) );
}
//
diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
index 7fb70cc32..c6b91cbf6 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
@@ -37,9 +37,11 @@ import java.util.ArrayList;
import java.util.List;
import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.ScalableSurface;
import com.jogamp.nativewindow.util.Rectangle;
import com.jogamp.nativewindow.util.RectangleImmutable;
+import jogamp.nativewindow.SurfaceScaleUtils;
import jogamp.nativewindow.x11.X11Util;
import jogamp.newt.Debug;
import jogamp.newt.DisplayImpl;
@@ -57,11 +59,27 @@ 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 boolean global_pixel_scale_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" };
+ int var_name_idx = -1;
+ try {
+ var_name_idx = SurfaceScaleUtils.getGlobalPixelScaleEnv(env_var_names, global_pixel_scale);
+ } catch (final Throwable t) { t.printStackTrace(); }
+ if( 0 <= var_name_idx && var_name_idx < env_var_names.length ) {
+ global_pixel_scale_set = true;
+ if( DEBUG ) {
+ System.err.println("X11Screen: Global PixelScale Set: "+env_var_names[var_name_idx]+": "+global_pixel_scale[0]+"/"+global_pixel_scale[1]);
+ }
+ } else {
+ global_pixel_scale_set = false;
+ }
+
DisplayDriver.initSingleton();
}
@@ -120,6 +138,10 @@ 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;
@@ -155,7 +177,8 @@ 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 ) {
- MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, null, monitorProps, 0, null);
+ MonitorModeProps.streamInMonitorDevice(cache, this, crt_id, pixel_scale, true /* invscale_wuviewport */,
+ monitorProps, 0, null);
}
}
}
@@ -177,6 +200,7 @@ public class ScreenDriver extends ScreenImpl {
if( null != viewportProps ) {
viewportPU.set(viewportProps[0], viewportProps[1], viewportProps[2], viewportProps[3]);
viewportWU.set(viewportProps[0], viewportProps[1], viewportProps[2], viewportProps[3]); // equal window-units and pixel-units
+ viewportWU.scaleInv(pixelScale[0], pixelScale[1]);
return true;
} else {
return false;
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index c1a24797b..38c463e7c 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -36,6 +36,8 @@ package jogamp.newt.driver.x11;
import java.nio.Buffer;
+import jogamp.nativewindow.SurfaceScaleUtils;
+import jogamp.nativewindow.windows.GDIUtil;
import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
import jogamp.newt.DisplayImpl;
@@ -53,9 +55,11 @@ import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.event.InputEvent;
import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.MonitorEvent;
import com.jogamp.newt.event.MouseEvent;
public class WindowDriver extends WindowImpl {
@@ -68,6 +72,8 @@ public class WindowDriver extends WindowImpl {
private static final int defaultIconDataSize;
private static final Buffer defaultIconData;
+ private volatile MonitorDevice last_monitor;
+
static {
ScreenDriver.initSingleton();
@@ -94,8 +100,45 @@ public class WindowDriver extends WindowImpl {
public WindowDriver() {
}
+ /**
+ * Essentially updates {@code hasPixelScale}
+ */
+ private boolean updatePixelScaleByMonitor(final MonitorDevice md, final int[] move_diff, final boolean sendEvent, final boolean defer) {
+ boolean res = false;
+ if( null != md ) {
+ final float newPixelScale[] = { 0, 0 };
+ md.getPixelScale(newPixelScale);
+ res = applySoftPixelScale(move_diff, sendEvent, defer, newPixelScale);
+ }
+ return res;
+ }
+
+ @Override
+ protected void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ if( last_monitor == me.getMonitor() ) {
+ updatePixelScaleByMonitor(me.getMonitor(), null, false /* sendEvent*/, false /* defer */); // send reshape event itself
+ }
+ }
+
@Override
- protected void createNativeImpl(boolean[] positionModified) {
+ public final boolean setSurfaceScale(final float[] pixelScale) {
+ super.setSurfaceScale(pixelScale); // pixelScale -> reqPixelScale
+
+ boolean changed = false;
+ if( isNativeValid() ) {
+ changed = applySoftPixelScale(null, true /* sendEvent */, false /* defer */, reqPixelScale);
+ }
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.setPixelScale: min["+minPixelScale[0]+", "+minPixelScale[1]+"], max["+
+ maxPixelScale[0]+", "+maxPixelScale[1]+"], req["+
+ reqPixelScale[0]+", "+reqPixelScale[1]+"] -> result["+
+ hasPixelScale[0]+", "+hasPixelScale[1]+"] - changed "+changed+", realized "+isNativeValid());
+ }
+ return changed;
+ }
+
+ @Override
+ protected void createNativeImpl(final boolean[] positionModified) {
final ScreenDriver screen = (ScreenDriver) getScreen();
final DisplayDriver display = (DisplayDriver) screen.getDisplay();
final AbstractGraphicsDevice edtDevice = display.getGraphicsDevice();
@@ -124,11 +167,14 @@ public class WindowDriver extends WindowImpl {
setGraphicsConfiguration(cfg);
final int flags = getReconfigureMask(0, true) & STATE_MASK_CREATENATIVE;
edtDevice.lock();
+
+ final int[] xy_pix = getPixelPosI();
+ final int[] sz_pix = getPixelSizeI();
try {
final long[] handles = CreateWindow(getParentWindowHandle(),
edtDevice.getHandle(), screen.getIndex(), visualID,
display.getJavaObjectAtom(), display.getWindowDeleteAtom(), display.getXiOpcode(),
- getX(), getY(), getWidth(), getHeight(), flags,
+ xy_pix[0], xy_pix[1], sz_pix[0], sz_pix[1], flags,
defaultIconDataSize, defaultIconData, DEBUG_IMPLEMENTATION);
if (null == handles || 2 != handles.length || 0 == handles[0] || 0 == handles[1] ) {
throw new NativeWindowException("Error creating window");
@@ -138,6 +184,14 @@ public class WindowDriver extends WindowImpl {
}
setWindowHandle(handles[0]);
javaWindowHandle = handles[1];
+
+ last_monitor = getMainMonitor();
+ boolean changedPixelScale = applySoftPixelScale(null, true /* sendEvent */, false /* defer */, reqPixelScale);
+ if( !changedPixelScale ) {
+ changedPixelScale = updatePixelScaleByMonitor(last_monitor, null, true /* sendEvent */, false /* defer */);
+ }
+ positionModified[0] = changedPixelScale;
+
} finally {
edtDevice.unlock();
}
@@ -160,6 +214,7 @@ public class WindowDriver extends WindowImpl {
} finally {
edtDevice.unlock();
javaWindowHandle = 0;
+ last_monitor = null;
}
}
if(null != renderDevice) {
@@ -200,9 +255,13 @@ public class WindowDriver extends WindowImpl {
_x = x;
_y = y;
}
+ final int xy_pix[] = SurfaceScaleUtils.scale(new int[2], _x, _y, hasPixelScale);
+ final int sz_pix[] = SurfaceScaleUtils.scale(new int[2], width, height, hasPixelScale);
+
if(DEBUG_IMPLEMENTATION) {
- System.err.println("X11Window reconfig.0: "+x+"/"+y+" -> "+_x+"/"+_y+" "+width+"x"+height+", insets "+_insets+
- ", "+getReconfigStateMaskString(flags));
+ System.err.println("X11Window reconfig.0: "+x+"/"+y+" -> "+_x+"/"+_y+" "+width+"x"+height+
+ " -> pixel["+xy_pix[0]+"/"+xy_pix[1]+" "+sz_pix[0]+"x"+sz_pix[1]+
+ "], insets "+_insets+", "+getReconfigStateMaskString(flags));
}
if( 0 != ( CHANGE_MASK_FULLSCREEN & flags ) ) {
if( 0 != ( STATE_MASK_FULLSCREEN & flags) &&
@@ -222,7 +281,7 @@ public class WindowDriver extends WindowImpl {
@Override
public Object run(final long dpy) {
reconfigureWindow0( dpy, getScreenIndex(),
- getParentWindowHandle(), javaWindowHandle, _x, _y, width, height, fflags);
+ getParentWindowHandle(), javaWindowHandle, xy_pix[0], xy_pix[1], sz_pix[0], sz_pix[1], fflags);
return null;
}
});
@@ -259,6 +318,32 @@ public class WindowDriver extends WindowImpl {
super.focusChanged(defer, focusGained);
}
+ @Override
+ protected boolean positionChanged(final boolean defer, final boolean windowUnits, final int newX, final int newY) {
+ final boolean res = super.positionChanged(defer, windowUnits, newX, newY);
+
+ if ( res ) {
+ if( isNativeValid() ) {
+ final MonitorDevice new_monitor = getMainMonitor();
+ if( null != last_monitor && !new_monitor.equals(last_monitor) ) {
+ final int[] move_diff = new int[] { 0, 0 };
+ MonitorDevice.Orientation orientation = MonitorDevice.Orientation.clone;
+ // Move from last_monitor -> new_monitor
+ orientation = new_monitor.getOrientationTo(last_monitor, move_diff);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Info: Window Device Changed (P: "+newX+"/"+newY+
+ ", crt_move[orient "+orientation+", diff "+move_diff[0]+"/"+move_diff[1]+") "+
+ ", monitor "+last_monitor.getId()+" -> "+new_monitor.getId()+
+ " - "+Thread.currentThread().getName());
+ }
+ last_monitor = new_monitor;
+ updatePixelScaleByMonitor(new_monitor, move_diff, true /* sendEvent */, defer);
+ }
+ }
+ }
+ return res;
+ }
+
protected void reparentNotify(final long newParentWindowHandle) {
if(DEBUG_IMPLEMENTATION) {
final long p0 = getParentWindowHandle();
@@ -344,12 +429,14 @@ public class WindowDriver extends WindowImpl {
@Override
protected Point getLocationOnScreenImpl(final int x, final int y) {
- return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Point>() {
+ final int xy_pix[] = SurfaceScaleUtils.scale(new int[2], x, y, hasPixelScale);
+ final Point res_pix = runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Point>() {
@Override
public Point run(final long dpy) {
- return X11Lib.GetRelativeLocation(dpy, getScreenIndex(), getWindowHandle(), 0 /*root win*/, x, y);
+ return X11Lib.GetRelativeLocation(dpy, getScreenIndex(), getWindowHandle(), 0 /*root win*/, xy_pix[0], xy_pix[1]);
}
} );
+ return convertToWindowUnits( res_pix );
}
@Override