Jogamp
Bug 1120 - Refine HiDPI Support ( Part-2 ) (API CHANGE)
authorSven Gothel <sgothel@jausoft.com>
Mon, 26 Jan 2015 23:49:51 +0000 (00:49 +0100)
committerSven Gothel <sgothel@jausoft.com>
Mon, 26 Jan 2015 23:49:51 +0000 (00:49 +0100)
- Use float[2] for pixel-scale.
  Utilize simple integer rounding:
    int-pixel-units = (int) ( int-window-units * pixel-scale + 0.5f )

- Provide minimum and maximum allowed pixel-scale values
  to be set by platform, supporting generic pixel-scale validation.

- Remove 'OSXUtil.GetPixelScale(final RectangleImmutable r, final int[] screenIndexOut)',
  implementation for all platforms would cause huge redundancy of
  Screen and MonitorDevice code (duplication of NEWT).

- instead, add 'float[2] pixelScale' to NEWT's MonitorDevice

- Detect change of pixel-scale and propagate accordingly.
  This allows GLCanvas, GLJPanel and NewtCanvasAWT instances
  to be dragged between monitor devices w/ different pixel-scale.

- OSX: Handle native triggered reshape events off-thread to avoid EDT congestion
       due to locked window when consuming deferred events on EDT.

46 files changed:
make/scripts/tests.sh
src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java
src/nativewindow/classes/javax/media/nativewindow/ScalableSurface.java
src/nativewindow/classes/javax/media/nativewindow/util/Point.java
src/nativewindow/classes/jogamp/nativewindow/SurfaceScaleUtils.java
src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
src/nativewindow/classes/jogamp/nativewindow/jawt/JAWTUtil.java
src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
src/nativewindow/native/macosx/OSXmisc.m
src/newt/classes/com/jogamp/newt/MonitorDevice.java
src/newt/classes/com/jogamp/newt/Window.java
src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
src/newt/classes/jogamp/newt/MonitorDeviceImpl.java
src/newt/classes/jogamp/newt/MonitorModeProps.java
src/newt/classes/jogamp/newt/ScreenImpl.java
src/newt/classes/jogamp/newt/WindowImpl.java
src/newt/classes/jogamp/newt/driver/android/ScreenDriver.java
src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java
src/newt/classes/jogamp/newt/driver/awt/ScreenDriver.java
src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
src/newt/classes/jogamp/newt/driver/bcm/egl/ScreenDriver.java
src/newt/classes/jogamp/newt/driver/bcm/vc/iv/ScreenDriver.java
src/newt/classes/jogamp/newt/driver/intel/gdl/ScreenDriver.java
src/newt/classes/jogamp/newt/driver/kd/ScreenDriver.java
src/newt/classes/jogamp/newt/driver/macosx/ScreenDriver.java
src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
src/newt/classes/jogamp/newt/driver/windows/ScreenDriver.java
src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
src/newt/native/MacWindow.m
src/newt/native/NewtMacWindow.m
src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneGLListener0A.java
src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtCanvasAWTDemo.java
src/test/com/jogamp/opengl/test/junit/graph/demos/GPUUISceneNewtDemo.java
src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLCanvasRecreate01.java
src/test/com/jogamp/opengl/test/junit/jogl/awt/TestAWT03GLJPanelRecreate01.java
src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2GLJPanelAWT.java
src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java
src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestRulerNEWT01.java
src/test/com/jogamp/opengl/test/junit/newt/mm/TestScreenMode00aNEWT.java

index 8711384..5c44050 100644 (file)
@@ -161,7 +161,7 @@ function jrun() {
     #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.ProxySurface -Djogl.debug.GLProfile"
     #D_ARGS="-Djogl.disable.surfacelesscontext -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Djogl.debug.GLJPanel -Djogl.debug.DebugGL"
     #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLJPanel -Djogl.debug.DebugGL"
-    D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLJPanel"
+    #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLJPanel"
     #D_ARGS="-Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLJPanel"
     #D_ARGS="-Djogl.debug.GLJPanel"
     #D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing"
@@ -231,7 +231,7 @@ function jrun() {
     #D_ARGS="-Dnewt.debug.EDT"
     #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext"
     #D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen"
-    #D_ARGS="-Dnativewindow.debug.JAWT -Dnewt.debug.Window -Djogl.debug.GLJPanel -Djogl.debug.GLCanvas"
+    D_ARGS="-Dnativewindow.debug.JAWT -Dnewt.debug.Window -Djogl.debug.GLJPanel -Djogl.debug.GLCanvas"
     #D_ARGS="-Dnewt.debug.Window.KeyEvent"
     #D_ARGS="-Dnewt.debug.Window.MouseEvent"
     #D_ARGS="-Dnewt.debug.Window.MouseEvent -Dnewt.debug.Window.KeyEvent"
index a648e3b..a3b84a8 100644 (file)
@@ -178,9 +178,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
   private volatile GLContextImpl context; // volatile: avoid locking for read-only access
   private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking
-  private final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-  private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-  final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+  private final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  private final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  final float[] reqPixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
 
   // copy of the cstr args, mainly for recreation
   private final GLCapabilitiesImmutable capsReqUser;
@@ -642,38 +643,73 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   }
 
   @Override
-  public final void setSurfaceScale(final int[] pixelScale) {
-      SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null);
-      if( isRealized() ) {
-          final ScalableSurface ns = jawtWindow;
-          if( null != ns ) {
-              ns.setSurfaceScale(reqPixelScale);
-              final int hadPixelScaleX = hasPixelScale[0];
-              final int hadPixelScaleY = hasPixelScale[1];
-              ns.getCurrentSurfaceScale(hasPixelScale);
-              if( hadPixelScaleX != hasPixelScale[0] || hadPixelScaleY != hasPixelScale[1] ) {
-                  reshapeImpl(getWidth(), getHeight());
-                  display();
-              }
-          }
+  public final boolean setSurfaceScale(final float[] pixelScale) {
+      System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2);
+      if( isRealized() && isShowing ) {
+          Threading.invoke(true, setSurfaceScaleOnEDTAction, getTreeLock());
+          return true;
+      } else {
+          return false;
+      }
+  }
+  private final Runnable setSurfaceScaleOnEDTAction = new Runnable() {
+    @Override
+    public void run() {
+        final RecursiveLock _lock = lock;
+        _lock.lock();
+        try {
+            if( null != drawable && drawable.isRealized() ) {
+                if( setSurfaceScaleImpl(jawtWindow) ) {
+                    reshapeImpl(getWidth(), getHeight());
+                    if( !helper.isAnimatorAnimatingOnOtherThread() ) {
+                        helper.invokeGL(drawable, context, displayAction, initAction); // display
+                    }
+                }
+            }
+        } finally {
+            _lock.unlock();
+        }
+    }  };
+  private final boolean setSurfaceScaleImpl(final ScalableSurface ns) {
+      if( ns.setSurfaceScale(reqPixelScale) ) {
+          ns.getCurrentSurfaceScale(hasPixelScale);
+          return true;
+      } else {
+          return false;
+      }
+  }
+
+  private final boolean updatePixelScale() {
+      if( jawtWindow.hasPixelScaleChanged() ) {
+          jawtWindow.getMaximumSurfaceScale(maxPixelScale);
+          jawtWindow.getMinimumSurfaceScale(minPixelScale);
+          return setSurfaceScaleImpl(jawtWindow);
+      } else {
+          return false;
       }
   }
 
   @Override
-  public final int[] getRequestedSurfaceScale(final int[] result) {
+  public final float[] getRequestedSurfaceScale(final float[] result) {
       System.arraycopy(reqPixelScale, 0, result, 0, 2);
       return result;
   }
 
   @Override
-  public final int[] getCurrentSurfaceScale(final int[] result) {
+  public final float[] getCurrentSurfaceScale(final float[] result) {
       System.arraycopy(hasPixelScale, 0, result, 0, 2);
       return result;
   }
 
   @Override
-  public int[] getNativeSurfaceScale(final int[] result) {
-      System.arraycopy(nativePixelScale, 0, result, 0, 2);
+  public float[] getMinimumSurfaceScale(final float[] result) {
+      System.arraycopy(minPixelScale, 0, result, 0, 2);
+      return result;
+  }
+
+  @Override
+  public float[] getMaximumSurfaceScale(final float[] result) {
+      System.arraycopy(maxPixelScale, 0, result, 0, 2);
       return result;
   }
 
@@ -681,13 +717,14 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
     if ( !Beans.isDesignTime() ) {
         jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
         jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
-        jawtWindow.setSurfaceScale(reqPixelScale);
         jawtWindow.lockSurface();
         try {
+            jawtWindow.setSurfaceScale(reqPixelScale);
             drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
             createContextImpl(drawable);
             jawtWindow.getCurrentSurfaceScale(hasPixelScale);
-            jawtWindow.getNativeSurfaceScale(nativePixelScale);
+            jawtWindow.getMinimumSurfaceScale(minPixelScale);
+            jawtWindow.getMaximumSurfaceScale(maxPixelScale);
         } finally {
             jawtWindow.unlockSurface();
         }
@@ -785,10 +822,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
         reshapeImpl(width, height);
     }
   }
-
   private void reshapeImpl(final int width, final int height) {
-    final int scaledWidth = width * hasPixelScale[0];
-    final int scaledHeight = height * hasPixelScale[1];
+    final int scaledWidth = SurfaceScaleUtils.scale(width, hasPixelScale[0]);
+    final int scaledHeight = SurfaceScaleUtils.scale(height, hasPixelScale[1]);
 
     if(DEBUG) {
         final NativeSurface ns = getNativeSurface();
@@ -1187,12 +1223,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
 
   @Override
   public int getSurfaceWidth() {
-      return getWidth() * hasPixelScale[0];
+      return SurfaceScaleUtils.scale(getWidth(), hasPixelScale[0]);
   }
 
   @Override
   public int getSurfaceHeight() {
-      return getHeight() * hasPixelScale[1];
+      return SurfaceScaleUtils.scale(getHeight(), hasPixelScale[1]);
   }
 
   @Override
@@ -1239,7 +1275,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
   // Internals only below this point
   //
 
-  private final String getPixelScaleStr() { return hasPixelScale[0]+"x"+hasPixelScale[1]; }
+  private final String getPixelScaleStr() { return "["+hasPixelScale[0]+", "+hasPixelScale[1]+"]"; }
 
   private final Runnable destroyOnEDTAction = new Runnable() {
     @Override
@@ -1339,8 +1375,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
         }
         hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
         hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
-        nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
-        nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+        minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+        minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+        maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+        maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
 
         if(null != awtConfig) {
             final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration();
@@ -1391,6 +1429,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
         _lock.lock();
         try {
             if( null != drawable && drawable.isRealized() ) {
+                if( GLCanvas.this.updatePixelScale() ) {
+                    GLCanvas.this.reshapeImpl(getWidth(), getHeight());
+                }
                 helper.invokeGL(drawable, context, displayAction, initAction);
             }
         } finally {
index 6e9e28c..65c4c55 100644 (file)
@@ -262,9 +262,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   private boolean handleReshape = false;
   private boolean sendReshape = true;
 
-  private final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-  private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-  private final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+  private final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  private final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  private final float[] reqPixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
 
   /** For handling reshape events lazily: reshapeWidth -> panelWidth -> backend.width in pixel units (scaled) */
   private int reshapeWidth;
@@ -450,20 +451,20 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
 
   @Override
   public void display() {
-    if( isShowing || ( printActive && isVisible() ) ) {
-        if (EventQueue.isDispatchThread()) {
-          // Want display() to be synchronous, so call paintImmediately()
-          paintImmediately(0, 0, getWidth(), getHeight());
-        } else {
-          // Multithreaded redrawing of Swing components is not allowed,
-          // so do everything on the event dispatch thread
-          try {
-            EventQueue.invokeAndWait(paintImmediatelyAction);
-          } catch (final Exception e) {
-            throw new GLException(e);
+      if( isShowing || ( printActive && isVisible() ) ) {
+          if (EventQueue.isDispatchThread()) {
+              // Want display() to be synchronous, so call paintImmediately()
+              paintImmediatelyAction.run();
+          } else {
+              // Multithreaded redrawing of Swing components is not allowed,
+              // so do everything on the event dispatch thread
+              try {
+                  EventQueue.invokeAndWait(paintImmediatelyAction);
+              } catch (final Exception e) {
+                  throw new GLException(e);
+              }
           }
-        }
-    }
+      }
   }
 
   protected void dispose(final Runnable post) {
@@ -556,6 +557,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
         // re-creating it -- tricky to do properly while the context is
         // current
         if( !printActive ) {
+            updatePixelScale(backend);
             if ( handleReshape ) {
                 handleReshape = false;
                 sendReshape = handleReshape();
@@ -579,36 +581,76 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   }
 
   @Override
-  public final void setSurfaceScale(final int[] pixelScale) { // HiDPI support
-      SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null);
-      final int hadPixelScaleX = hasPixelScale[0];
-      final int hadPixelScaleY = hasPixelScale[1];
-      SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null);
-      if( hadPixelScaleX != hasPixelScale[0] || hadPixelScaleY != hasPixelScale[1] ) {
-          reshapeImpl(getWidth(), getHeight());
-          final Backend b = backend;
-          if ( isInitialized && null != b ) {
-              updateWrappedSurfaceScale(b.getDrawable());
-              display();
+  public final boolean setSurfaceScale(final float[] pixelScale) { // HiDPI support
+      System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2);
+      final Backend b = backend;
+      if ( isInitialized && null != b && isShowing ) {
+          if( isShowing || ( printActive && isVisible() ) ) {
+              if (EventQueue.isDispatchThread()) {
+                  setSurfaceScaleAction.run();
+              } else {
+                  try {
+                      EventQueue.invokeAndWait(setSurfaceScaleAction);
+                  } catch (final Exception e) {
+                      throw new GLException(e);
+                  }
+              }
           }
+          return true;
+      } else {
+          return false;
+      }
+  }
+  private final Runnable setSurfaceScaleAction = new Runnable() {
+    @Override
+    public void run() {
+        final Backend b = backend;
+        if( null != b && setSurfaceScaleImpl(b) ) {
+            if( !helper.isAnimatorAnimatingOnOtherThread() ) {
+                paintImmediatelyAction.run(); // display
+            }
+        }
+    }
+  };
+
+  private final boolean setSurfaceScaleImpl(final Backend b) {
+      if( SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null) ) {
+          reshapeImpl(getWidth(), getHeight());
+          updateWrappedSurfaceScale(b.getDrawable());
+          return true;
+      }
+      return false;
+  }
+
+  private final boolean updatePixelScale(final Backend b) {
+      if( JAWTUtil.getPixelScale(getGraphicsConfiguration(), minPixelScale, maxPixelScale) ) {
+          return setSurfaceScaleImpl(b);
+      } else {
+          return false;
       }
   }
 
   @Override
-  public final int[] getRequestedSurfaceScale(final int[] result) {
+  public final float[] getRequestedSurfaceScale(final float[] result) {
       System.arraycopy(reqPixelScale, 0, result, 0, 2);
       return result;
   }
 
   @Override
-  public final int[] getCurrentSurfaceScale(final int[] result) {
+  public final float[] getCurrentSurfaceScale(final float[] result) {
       System.arraycopy(hasPixelScale, 0, result, 0, 2);
       return result;
   }
 
   @Override
-  public int[] getNativeSurfaceScale(final int[] result) {
-      System.arraycopy(nativePixelScale, 0, result, 0, 2);
+  public float[] getMinimumSurfaceScale(final float[] result) {
+      System.arraycopy(minPixelScale, 0, result, 0, 2);
+      return result;
+  }
+
+  @Override
+  public float[] getMaximumSurfaceScale(final float[] result) {
+      System.arraycopy(maxPixelScale, 0, result, 0, 2);
       return result;
   }
 
@@ -624,12 +666,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     awtWindowClosingProtocol.addClosingListener();
 
     // HiDPI support
-    {
-        final int ps = JAWTUtil.getPixelScale(getGraphicsConfiguration());
-        nativePixelScale[0] = ps;
-        nativePixelScale[1] = ps;
-    }
-    SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null);
+    JAWTUtil.getPixelScale(getGraphicsConfiguration(), minPixelScale, maxPixelScale);
+    SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null);
 
     if (DEBUG) {
         System.err.println(getThreadName()+": GLJPanel.addNotify()");
@@ -649,8 +687,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     dispose(null);
     hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
     hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
-    nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
-    nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+    minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+    minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+    maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+    maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
 
     super.removeNotify();
   }
@@ -670,8 +710,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
   }
 
   private void reshapeImpl(final int width, final int height) {
-    final int scaledWidth = width * hasPixelScale[0];
-    final int scaledHeight = height * hasPixelScale[1];
+    final int scaledWidth = SurfaceScaleUtils.scale(width, hasPixelScale[0]);
+    final int scaledHeight = SurfaceScaleUtils.scale(height, hasPixelScale[1]);
     if( !printActive && ( handleReshape || scaledWidth != panelWidth || scaledHeight != panelHeight ) ) {
         reshapeWidth = scaledWidth;
         reshapeHeight = scaledHeight;
@@ -826,8 +866,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
               // trigger reshape, i.e. gl-viewport and -listener - this component might got resized!
               final int awtWidth = GLJPanel.this.getWidth();
               final int awtHeight= GLJPanel.this.getHeight();
-              final int scaledAWTWidth = awtWidth * hasPixelScale[0];
-              final int scaledAWTHeight= awtHeight * hasPixelScale[1];
+              final int scaledAWTWidth = SurfaceScaleUtils.scale(awtWidth, hasPixelScale[0]);
+              final int scaledAWTHeight= SurfaceScaleUtils.scale(awtHeight, hasPixelScale[1]);
               final GLDrawable drawable = GLJPanel.this.getDelegatedDrawable();
               if( scaledAWTWidth != panelWidth || scaledAWTHeight != panelHeight ||
                   drawable.getSurfaceWidth() != panelWidth || drawable.getSurfaceHeight() != panelHeight ) {
@@ -1342,7 +1382,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
     }
   }
 
-  private final String getPixelScaleStr() { return hasPixelScale[0]+"x"+hasPixelScale[1]; }
+  private final String getPixelScaleStr() { return "["+hasPixelScale[0]+", "+hasPixelScale[1]+"]"; }
 
   @Override
   public WindowClosingMode getDefaultCloseOperation() {
@@ -2058,7 +2098,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
             System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.doPaintComponent.drawImage: - frameCount "+frameCount);
         }
         // Draw resulting image in one shot
-        g.drawImage(alignedImage, 0, 0, alignedImage.getWidth()/hasPixelScale[0], alignedImage.getHeight()/hasPixelScale[1], null); // Null ImageObserver since image data is ready.
+        g.drawImage(alignedImage, 0, 0,
+                    SurfaceScaleUtils.scaleInv(alignedImage.getWidth(), hasPixelScale[0]),
+                    SurfaceScaleUtils.scaleInv(alignedImage.getHeight(), hasPixelScale[1]), null); // Null ImageObserver since image data is ready.
       }
       frameCount++;
     }
index 32e4add..97dba95 100644 (file)
@@ -47,6 +47,8 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration;
 import java.awt.Component;
 import java.awt.Container;
 import java.awt.Cursor;
+import java.awt.EventQueue;
+import java.awt.GraphicsConfiguration;
 import java.awt.Window;
 import java.awt.event.ComponentEvent;
 import java.awt.event.ComponentListener;
@@ -103,10 +105,11 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
   protected Insets insets;
   private volatile long offscreenSurfaceLayer;
 
-  private final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-  private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-  protected final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
-
+  private final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  private final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  private final float[] reqPixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+  private volatile boolean hasPixelScaleChanged = false;
   private long drawable_old;
 
   /**
@@ -269,38 +272,41 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
     insets = new Insets();
     hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
     hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
-    nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
-    nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+    minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+    minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+    maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+    maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+    hasPixelScaleChanged = false;
   }
   protected abstract void invalidateNative();
 
-  /**
-   * {@inheritDoc}
-   * <p>
-   * Per default impl. only works for not yet {@link #isRealized() realized} instances,
-   * current exception OSX.
-   * </p>
-   */
   @Override
-  public void setSurfaceScale(final int[] pixelScale) {
-      SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG ? getClass().getSimpleName() : null);
+  public boolean setSurfaceScale(final float[] pixelScale) {
+      System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2);
+      return false;
   }
 
   @Override
-  public final int[] getRequestedSurfaceScale(final int[] result) {
+  public final float[] getRequestedSurfaceScale(final float[] result) {
       System.arraycopy(reqPixelScale, 0, result, 0, 2);
       return result;
   }
 
   @Override
-  public final int[] getCurrentSurfaceScale(final int[] result) {
+  public final float[] getCurrentSurfaceScale(final float[] result) {
       System.arraycopy(hasPixelScale, 0, result, 0, 2);
       return result;
   }
 
   @Override
-  public final int[] getNativeSurfaceScale(final int[] result) {
-      System.arraycopy(nativePixelScale, 0, result, 0, 2);
+  public float[] getMinimumSurfaceScale(final float[] result) {
+      System.arraycopy(minPixelScale, 0, result, 0, 2);
+      return result;
+  }
+
+  @Override
+  public final float[] getMaximumSurfaceScale(final float[] result) {
+      System.arraycopy(maxPixelScale, 0, result, 0, 2);
       return result;
   }
 
@@ -323,31 +329,75 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
             insets.set(contInsets.left, contInsets.right, contInsets.top, contInsets.bottom);
         }
     }
-    {
-        final int ps = JAWTUtil.getPixelScale(config.getAWTGraphicsConfiguration());
-        nativePixelScale[0] = ps;
-        nativePixelScale[1] = ps;
-    }
 
-    return updatePixelScale() || changedBounds;
+    updatePixelScale(false);
+    return hasPixelScaleChanged || changedBounds;
+  }
+
+  /**
+   * Updates the minimum and maximum pixel-scale values
+   * and returns {@code true} if they were updated.
+   * @param clearFlag if {@code true}, the {@code hasPixelScaleChanged} flag will be cleared
+   * @return {@code true} if values were updated, otherwise {@code false}.
+   * @see #hasPixelScaleChanged()
+   */
+  public final boolean updatePixelScale(final boolean clearFlag) {
+      // Using GraphicsConfiguration from component, which may change by moving to diff monitor
+      if( EventQueue.isDispatchThread() || Thread.holdsLock(component.getTreeLock()) ) {
+          if( JAWTUtil.getPixelScale(component.getGraphicsConfiguration(), minPixelScale, maxPixelScale) ) {
+              hasPixelScaleChanged = true;
+              if( DEBUG ) {
+                  System.err.println("JAWTWindow.updatePixelScale: updated req["+
+                          reqPixelScale[0]+", "+reqPixelScale[1]+"], min["+
+                          minPixelScale[0]+", "+minPixelScale[1]+"], max["+
+                          maxPixelScale[0]+", "+maxPixelScale[1]+"], has["+
+                          hasPixelScale[0]+", "+hasPixelScale[1]+"]");
+              }
+          }
+      }
+      if( clearFlag ) {
+          final boolean r = hasPixelScaleChanged;
+          hasPixelScaleChanged = false;
+          return r;
+      } else {
+          return hasPixelScaleChanged;
+      }
+  }
+
+  /**
+   * Returns and clears the {@code hasPixelScaleChanged} flag, as set via {@link #lockSurface()}.
+   * <p>
+   * {@code hasPixelScaleChanged} is {@code true},
+   * if the {@link #getMinimumSurfaceScale(float[]) minimum} or {@link #getMaximumSurfaceScale(float[]) maximum}
+   * pixel scale has changed.
+   * User needs to {@link #setSurfaceScale(float[]) set the current pixel scale} in this case
+   * using the {@link #getRequestedSurfaceScale(float[]) requested pixel scale}
+   * to update the surface pixel scale.
+   * </p>
+   */
+  public final boolean hasPixelScaleChanged() {
+      final boolean v = hasPixelScaleChanged;
+      hasPixelScaleChanged = false;
+      return v;
   }
 
   /**
-   * Update pixelScale
+   * set requested pixelScale
    * @return true if pixelScale has changed, otherwise false
    */
-  protected final boolean updatePixelScale() {
-    return SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, nativePixelScale, DEBUG ? getClass().getSimpleName() : null);
+  protected final boolean setReqPixelScale() {
+    updatePixelScale(true);
+    return SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null);
   }
 
   /** @return the JAWT_DrawingSurfaceInfo's (JAWT_Rectangle) bounds, updated with lock */
   public final RectangleImmutable getBounds() { return bounds; }
 
   /** @return the safe pixelScale value for x-direction, i.e. never negative or zero. Updated with lock. */
-  protected final int getPixelScaleX() { return hasPixelScale[0]; }
+  protected final float getPixelScaleX() { return hasPixelScale[0]; }
 
   /** @return the safe pixelScale value for y-direction, i.e. never negative or zero. Updated with lock. */
-  protected final int getPixelScaleY() { return hasPixelScale[1]; }
+  protected final float getPixelScaleY() { return hasPixelScale[1]; }
 
   @Override
   public final InsetsImmutable getInsets() { return insets; }
@@ -671,26 +721,22 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
 
   @Override
   public final int getSurfaceWidth() {
-    return getWidth() * getPixelScaleX();
+    return SurfaceScaleUtils.scale(getWidth(), getPixelScaleX());
   }
 
   @Override
   public final int getSurfaceHeight() {
-    return getHeight() * getPixelScaleY();
+    return SurfaceScaleUtils.scale(getHeight(), getPixelScaleY());
   }
 
   @Override
   public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
-      pixelUnitsAndResult[0] /= getPixelScaleX();
-      pixelUnitsAndResult[1] /= getPixelScaleY();
-      return pixelUnitsAndResult;
+      return SurfaceScaleUtils.scaleInv(pixelUnitsAndResult, pixelUnitsAndResult, hasPixelScale);
   }
 
   @Override
   public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
-      windowUnitsAndResult[0] *= getPixelScaleX();
-      windowUnitsAndResult[1] *= getPixelScaleY();
-      return windowUnitsAndResult;
+      return SurfaceScaleUtils.scale(windowUnitsAndResult, windowUnitsAndResult, hasPixelScale);
   }
 
   @Override
@@ -874,7 +920,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
                 ", bounds "+bounds+", insets "+insets
                 );
     sb.append(", window ["+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+
-             "], pixels[s "+getPixelScaleX()+"x"+getPixelScaleY()+" -> "+getSurfaceWidth()+"x"+getSurfaceHeight()+"]"+
+             "], pixels[scale "+getPixelScaleX()+", "+getPixelScaleY()+" -> "+getSurfaceWidth()+"x"+getSurfaceHeight()+"]"+
               ", visible "+component.isVisible());
     sb.append(", lockedExt "+isSurfaceLockedByOtherThread()+
               ",\n\tconfig "+config+
index 4d764dc..d5ac561 100644 (file)
@@ -198,6 +198,7 @@ public interface NativeSurface extends SurfaceUpdatedListener {
    * @param pixelUnitsAndResult int[2] storage holding the pixel units for the x- and y-coord to convert
    *                             and the resulting values.
    * @return result int[2] storage pixelUnitsAndResult for chaining holding the converted values
+   * @see ScalableSurface
    */
   public int[] convertToWindowUnits(final int[] pixelUnitsAndResult);
 
@@ -206,6 +207,7 @@ public interface NativeSurface extends SurfaceUpdatedListener {
    * @param windowUnitsAndResult int[2] storage holding the window units for the x- and y-coord to convert
    *                             and the resulting values.
    * @return result int[2] storage windowUnitsAndResult for chaining holding the converted values
+   * @see ScalableSurface
    */
   public int[] convertToPixelUnits(final int[] windowUnitsAndResult);
 
index ffd5c22..0cd2c79 100644 (file)
@@ -30,16 +30,17 @@ package javax.media.nativewindow;
 
 /**
  * Adding mutable surface pixel scale property to implementing class, usually to a {@link NativeSurface} implementation,
- * see {@link #setSurfaceScale(int[])}.
+ * see {@link #setSurfaceScale(float[])}.
  */
 public interface ScalableSurface {
   /** Setting surface-pixel-scale of {@value}, results in same pixel- and window-units. */
-  public static final int IDENTITY_PIXELSCALE = 1;
+  public static final float IDENTITY_PIXELSCALE = 1f;
   /** Setting surface-pixel-scale of {@value}, results in maximum platform dependent pixel-scale, i.e. pixel-units >> window-units where available. */
-  public static final int AUTOMAX_PIXELSCALE = 0;
+  public static final float AUTOMAX_PIXELSCALE = 0f;
 
   /**
-   * Request a pixel scale in x- and y-direction for the associated {@link NativeSurface}.
+   * Request a pixel scale in x- and y-direction for the associated {@link NativeSurface},
+   * where {@code size_in_pixel_units = pixel_scale * size_in_window_units}.
    * <p>
    * Default pixel scale request for both directions is {@link #AUTOMAX_PIXELSCALE}.
    * </p>
@@ -50,48 +51,57 @@ public interface ScalableSurface {
    * <p>
    * The <i>requested</i> pixel scale will be validated against platform limits before native scale-setup,
    * i.e. clipped to {@link #IDENTITY_PIXELSCALE} if not supported or clipped to the platform maximum.
-   * It can be queried via {@link #getRequestedSurfaceScale(int[])}.
+   * It can be queried via {@link #getRequestedSurfaceScale(float[])}.
    * </p>
    * <p>
    * The actual <i>realized</i> pixel scale values of the {@link NativeSurface}
-   * can be queried via {@link #getCurrentSurfaceScale(int[])} or
+   * can be queried via {@link #getCurrentSurfaceScale(float[])} or
    * computed via <code>surface.{@link NativeSurface#convertToPixelUnits(int[]) convertToPixelUnits}(new int[] { 1, 1 })</code>
    * </p>
- * @param pixelScale <i>requested</i> surface pixel scale int[2] values for x- and y-direction.
+   * @param pixelScale <i>requested</i> surface pixel scale float[2] values for x- and y-direction.
+   * @return {@code true} if the {@link #getCurrentSurfaceScale(float[]) current pixel scale} has changed, otherwise {@code false}.
+   * @see #getRequestedSurfaceScale(float[])
    */
-  public void setSurfaceScale(final int[] pixelScale);
+  public boolean setSurfaceScale(final float[] pixelScale);
 
   /**
-   * Returns the requested pixel scale of the associated {@link NativeSurface}.
+   * Returns the {@link #setSurfaceScale(float[]) requested} pixel scale of the associated {@link NativeSurface}.
    *
-   * @param result int[2] storage for the result
-   * @return the passed storage containing the requested pixelScale for chaining
+   * @param result float[2] storage for the result
+   * @return the passed storage containing the current pixelScale for chaining
+   * @see #setSurfaceScale(float[])
    */
-  int[] getRequestedSurfaceScale(final int[] result);
+  public float[] getRequestedSurfaceScale(final float[] result);
 
   /**
    * Returns the current pixel scale of the associated {@link NativeSurface}.
    *
-   * @param result int[2] storage for the result
+   * @param result float[2] storage for the result
    * @return the passed storage containing the current pixelScale for chaining
    */
-  public int[] getCurrentSurfaceScale(final int[] result);
+  public float[] getCurrentSurfaceScale(final float[] result);
+
+  /**
+   * Returns the minimum pixel scale of the associated {@link NativeSurface}.
+   * @param result float[2] storage for the result
+   * @return the passed storage containing the minimum pixelScale for chaining
+   */
+  public float[] getMinimumSurfaceScale(final float[] result);
 
   /**
-   * Returns the native pixel scale of the associated {@link NativeSurface}
-   * reflecting it's currently bound <i>monitor surface resolution in pixels</i>.
+   * Returns the maximum pixel scale of the associated {@link NativeSurface}.
    * <p>
-   * The native pixel scale maybe used to determine the proper <i>dpi</i>
-   * value of this {@link NativeSurface}:
+   * The maximum pixel scale maybe used to determine the proper <i>dpi</i>
+   * value of the monitor displaying this {@link NativeSurface}.
    * <pre>
    *    surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale,
    *    with PpMM == pixel per millimeter
    * </pre>
    * </p>
    *
-   * @param result int[2] storage for the result
-   * @return the passed storage containing the native pixelScale for chaining
+   * @param result float[2] storage for the result
+   * @return the passed storage containing the maximum pixelScale for chaining
    */
-  public int[] getNativeSurfaceScale(final int[] result);
+  public float[] getMaximumSurfaceScale(final float[] result);
 }
 
index 3576a7d..3d416d2 100644 (file)
@@ -145,6 +145,22 @@ public class Point implements Cloneable, PointImmutable {
     }
 
     /**
+     * Scale this instance's x- and y-components,
+     * i.e. multiply them by the given scale factors.
+     * <p>
+     * The product is rounded back to integer.
+     * </p>
+     * @param sx scale factor for x
+     * @param sy scale factor for y
+     * @return this instance for scaling
+     */
+    public final Point scale(final float sx, final float sy) {
+        x = (int)(x * sx + 0.5f);
+        y = (int)(y * sy + 0.5f);
+        return this;
+    }
+
+    /**
      * Inverse scale this instance's x- and y-components,
      * i.e. divide them by the given scale factors.
      * @param sx inverse scale factor for x
@@ -156,4 +172,19 @@ public class Point implements Cloneable, PointImmutable {
         y /= sy ;
         return this;
     }
+    /**
+     * Inverse scale this instance's x- and y-components,
+     * i.e. divide them by the given scale factors.
+     * <p>
+     * The product is rounded back to integer.
+     * </p>
+     * @param sx inverse scale factor for x
+     * @param sy inverse scale factor for y
+     * @return this instance for scaling
+     */
+    public final Point scaleInv(final float sx, final float sy) {
+        x = (int)(x / sx + 0.5f);
+        y = (int)(y / sy + 0.5f);
+        return this;
+    }
 }
index 73413cf..70eec7b 100644 (file)
@@ -27,7 +27,6 @@
  */
 package jogamp.nativewindow;
 
-import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.nativewindow.ScalableSurface;
 
 /**
@@ -35,138 +34,162 @@ import javax.media.nativewindow.ScalableSurface;
  */
 public class SurfaceScaleUtils {
 
-    private static final int[] PlatformMaxPixelScale;
-    private static final boolean PlatformUniformPixelScale;
-    private static final boolean PlatformPixelScaleSupported;
+    private static final float EPSILON = 1.1920929E-7f; // Float.MIN_VALUE == 1.4e-45f ; double EPSILON 2.220446049250313E-16d
 
-    static {
-      if( NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(true) ) {
-          PlatformMaxPixelScale = new int[] { jogamp.nativewindow.macosx.OSXUtil.MAX_PIXELSCALE, jogamp.nativewindow.macosx.OSXUtil.MAX_PIXELSCALE };
-          PlatformUniformPixelScale = true;
-          PlatformPixelScaleSupported = true;
-      } else {
-          PlatformMaxPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-          PlatformUniformPixelScale = false;
-          PlatformPixelScaleSupported = false;
-      }
+    private static boolean isZero(final float a) {
+        return Math.abs(a) < EPSILON;
     }
 
     /**
-     * Compute a new valid pixelScale to be used by {@link NativeSurface} implementations,
-     * based on the given request and surface's pixelScale
+     * Returns integer rounded product, i.e. {@code (int) ( a * pixelScale + 0.5f )}
      *
-     * @param result int[2] storage for result, maybe same as <code>prePixelScale</code> for in-place
-     * @param prePixelScale previous pixelScale
-     * @param reqPixelScale requested pixelScale, validated via {@link #validateReqPixelScale(int[], int, String)}.
-     * @param newPixelScaleRaw new raw surface pixelScale
-     * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix
-     * @return true if pixelScale has changed, otherwise false
+     * @param a the int value
+     * @param pixelScale the float scale factor
+     * @return the integer rounded product
      */
-    public static boolean computePixelScale(final int[] result, final int[] prePixelScale, final int[] reqPixelScale, final int[] newPixelScaleRaw, final String DEBUG_PREFIX) {
-        final int newPixelScaleSafeX = 0 < newPixelScaleRaw[0] ? newPixelScaleRaw[0] : ScalableSurface.IDENTITY_PIXELSCALE;
-        final int newPixelScaleSafeY = 0 < newPixelScaleRaw[1] ? newPixelScaleRaw[1] : ScalableSurface.IDENTITY_PIXELSCALE;
-        final boolean useHiDPI = ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[0] || ScalableSurface.IDENTITY_PIXELSCALE != reqPixelScale[1];
-        final int prePixelScaleX = prePixelScale[0];
-        final int prePixelScaleY = prePixelScale[1];
-
-        if( useHiDPI ) {
-            result[0] = newPixelScaleSafeX;
-            result[1] = newPixelScaleSafeY;
-        } else {
-            result[0] = ScalableSurface.IDENTITY_PIXELSCALE;
-            result[1] = ScalableSurface.IDENTITY_PIXELSCALE;
-        }
-
-        final boolean changed = result[0] != prePixelScaleX || result[1] != prePixelScaleY;
-        if( null != DEBUG_PREFIX ) {
-            System.err.println(DEBUG_PREFIX+".computePixelScale: useHiDPI "+useHiDPI+", ["+prePixelScaleX+"x"+prePixelScaleY+" (pre), "+
-                    reqPixelScale[0]+"x"+reqPixelScale[1]+" (req)] -> "+
-                    newPixelScaleRaw[0]+"x"+newPixelScaleRaw[1]+" (raw) -> "+
-                    newPixelScaleSafeX+"x"+newPixelScaleSafeY+" (safe) -> "+
-                    result[0]+"x"+result[1]+" (use), changed "+changed);
-        }
-        return changed;
+    public static int scale(final int a, final float pixelScale) {
+        return (int) ( a * pixelScale + 0.5f );
     }
 
     /**
-     * Validate the given requested pixelScale value pair, i.e. clip it to the
-     * limits of {@link ScalableSurface#AUTOMAX_PIXELSCALE} and {@link #getPlatformMaxPixelScale(int[])}
-     * <p>
-     * To be used by {@link ScalableSurface#setSurfaceScale(int[])} implementations.
-     * </p>
+     * Returns integer rounded product, i.e. {@code (int) ( a / pixelScale + 0.5f )}
      *
-     * @param result int[2] storage for result
-     * @param reqPixelScale requested pixelScale
-     * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix
+     * @param a the int value
+     * @param pixelScale the float scale factor
+     * @return the integer rounded product
      */
-    public static void validateReqPixelScale(final int[] result, final int[] reqPixelScale, final String DEBUG_PREFIX) {
-        final int minPS = Math.min(reqPixelScale[0], reqPixelScale[1]);
-        if( ScalableSurface.AUTOMAX_PIXELSCALE >= minPS ) {
-            result[0] = ScalableSurface.AUTOMAX_PIXELSCALE;
-            result[1] = ScalableSurface.AUTOMAX_PIXELSCALE;
-        } else if( PlatformUniformPixelScale ) {
-            final int maxPS = Math.max(reqPixelScale[0], reqPixelScale[1]);
-            if( maxPS >= PlatformMaxPixelScale[0] ) {
-                result[0] = PlatformMaxPixelScale[0];
-                result[1] = PlatformMaxPixelScale[1];
-            } else {
-                result[0] = maxPS;
-                result[1] = maxPS;
-            }
-        } else {
-            if( reqPixelScale[0] >= PlatformMaxPixelScale[0] ) {
-                result[0] = PlatformMaxPixelScale[0];
-            } else {
-                result[0] = reqPixelScale[0];
-            }
-            if( reqPixelScale[1] >= PlatformMaxPixelScale[1] ) {
-                result[1] = PlatformMaxPixelScale[1];
-            } else {
-                result[1] = reqPixelScale[1];
-            }
-        }
-        if( null != DEBUG_PREFIX ) {
-            System.err.println(DEBUG_PREFIX+".validateReqPixelScale: ["+reqPixelScale[0]+"x"+reqPixelScale[1]+" (req), "+
-                    PlatformMaxPixelScale[0]+"x"+PlatformMaxPixelScale[1]+" (max)] -> "+
-                    result[0]+"x"+result[1]+" (valid)");
-        }
+    public static int scaleInv(final int a, final float pixelScale) {
+        return (int) ( a / pixelScale + 0.5f );
     }
 
     /**
-     * Replaces {@link ScalableSurface#AUTOMAX_PIXELSCALE} with {@link #getPlatformMaxPixelScale(int[])},
-     * for each component.
+     * Returns integer rounded product, i.e. {@code (int) ( a * pixelScale + 0.5f )}
      *
-     * @param pixelScale int[2] value array to be tested and replaced
+     * @param result the int[2] result, may be {@code a} for in-place operation
+     * @param a the int[2] values
+     * @param pixelScale the float[2] scale factors
+     * @return the result for chaining
      */
-    public static void replaceAutoMaxWithPlatformMax(final int[] pixelScale) {
-        if( ScalableSurface.AUTOMAX_PIXELSCALE == pixelScale[0] ) {
-            pixelScale[0] = PlatformMaxPixelScale[0];
-        }
-        if( ScalableSurface.AUTOMAX_PIXELSCALE == pixelScale[1] ) {
-            pixelScale[1] = PlatformMaxPixelScale[1];
-        }
+    public static int[] scale(final int[] result, final int[] a, final float[] pixelScale) {
+        result[0] = (int) ( a[0] * pixelScale[0] + 0.5f );
+        result[1] = (int) ( a[1] * pixelScale[1] + 0.5f );
+        return result;
     }
-
     /**
-     * Returns the maximum platform pixelScale
+     * Returns integer rounded product, i.e. {@code (int) ( a / pixelScale + 0.5f )}
+     *
+     * @param result the int[2] result, may be {@code a} for in-place operation
+     * @param a the int[2] values
+     * @param pixelScale the float[2] scale factors
+     * @return the result for chaining
      */
-    public static int[] getPlatformMaxPixelScale(final int[] result) {
-        System.arraycopy(PlatformMaxPixelScale, 0, result, 0, 2);
+    public static int[] scaleInv(final int[] result, final int[] a, final float[] pixelScale) {
+        result[0] = (int) ( a[0] / pixelScale[0] + 0.5f );
+        result[1] = (int) ( a[1] / pixelScale[1] + 0.5f );
         return result;
     }
 
     /**
-     * Returns true if platform pixelScale is uniform, i.e. same scale factor for x- and y-direction, otherwise false.
+     * Method constrains the given pixel-scale within ]0..{@code maxPixelScale}], as described below.
+     * <p>
+     * Method returns {@link ScalableSurface#IDENTITY_PIXELSCALE IDENTITY_PIXELSCALE} if:
+     * <ul>
+     *   <li>{@code pixelScale} ~= {@link ScalableSurface#IDENTITY_PIXELSCALE IDENTITY_PIXELSCALE}</li>
+     * </ul>
+     * </p>
+     * <p>
+     * Method returns {@code maxPixelScale} if
+     * <ul>
+     *   <li>{@code pixelScale} ~= {@link ScalableSurface#AUTOMAX_PIXELSCALE AUTOMAX_PIXELSCALE}</li>
+     *   <li>{@code pixelScale} &gt; {@code maxPixelScale}</li>
+     *   <li>{@code pixelScale} ~= {@code maxPixelScale}</li>
+     * </ul>
+     * </p>
+     * <p>
+     * Method returns {@code minPixelScale} if
+     * <ul>
+     *   <li>{@code pixelScale} &lt; {@code minPixelScale}</li>
+     *   <li>{@code pixelScale} ~= {@code minPixelScale}</li>
+     * </ul>
+     * </p>
+     * <p>
+     * Otherwise method returns the given {@code pixelScale}.
+     * </p>
+     * <p>
+     * <i>~=</i> denominates a delta &le; {@link FloatUtil#EPSILON}.
+     * </p>
+     * @param pixelScale pixel-scale to be constrained
+     * @param minPixelScale minimum pixel-scale
+     * @param maxPixelScale maximum pixel-scale
+     * @return the constrained pixel-scale
      */
-    public static boolean isPlatformPixelScaleUniform() {
-        return PlatformUniformPixelScale;
+    public static float clampPixelScale(final float pixelScale, final float minPixelScale, final float maxPixelScale) {
+        if( isZero(pixelScale-ScalableSurface.IDENTITY_PIXELSCALE) ) {
+            return ScalableSurface.IDENTITY_PIXELSCALE;
+        } else if( isZero(pixelScale-ScalableSurface.AUTOMAX_PIXELSCALE) ||
+                   pixelScale > maxPixelScale ||
+                   isZero(pixelScale-maxPixelScale)
+                 )
+        {
+            return maxPixelScale;
+        } else if( pixelScale < minPixelScale || isZero(pixelScale-minPixelScale) )
+        {
+            return minPixelScale;
+        } else {
+            return pixelScale;
+        }
     }
 
     /**
-     * Returns whether the platform supports pixelScale
+     * Method {@link #clampPixelScale(float, float, float) constrains} the given float[2] pixel-scale
+     * within ]0..{@code maxPixelScale}], as described in {@link #clampPixelScale(float, float, float)}.
+     *
+     * @param result float[2] storage for result, maybe same as <code>s</code> for in-place
+     * @param pixelScale float[2] pixelScale to be constrained
+     * @param minPixelScale float[2] minimum pixel-scale
+     * @param maxPixelScale float[2] maximum pixel-scale
+     * @return the constrained result for chaining
      */
-    public static boolean isPlatformPixelScaleSupported() {
-        return PlatformPixelScaleSupported;
+    public static float[] clampPixelScale(final float[] result, final float[] pixelScale,
+                                          final float[] minPixelScale, final float[] maxPixelScale) {
+        result[0] = clampPixelScale(pixelScale[0], minPixelScale[0], maxPixelScale[0]);
+        result[1] = clampPixelScale(pixelScale[1], minPixelScale[1], maxPixelScale[1]);
+        return result;
     }
 
+    /**
+     * Method writes the given float[2] requested pixel-scale {@code reqPixelScale}
+     * into {@code result} within its constraints ]0..{@code maxPixelScale}], as described in {@link #clampPixelScale(float, float, float)}.
+     * <p>
+     * Method only differs from {@link #clampPixelScale(float[], float[], float[], float[])}
+     * by returning the whether the value has changed, i.e. different from the given {@code prePixelScale}.
+     * </p>
+     *
+     * @param result int[2] storage for result, maybe same as <code>prePixelScale</code> for in-place
+     * @param prePixelScale float[2] previous pixel-scale
+     * @param reqPixelScale float[2] requested pixel-scale, validated via {@link #validateReqPixelScale(float[], float[], String)}.
+     * @param minPixelScale float[2] minimum pixel-scale
+     * @param maxPixelScale float[2] maximum pixel-scale
+     * @param DEBUG_PREFIX if set, dumps debug info on stderr using this prefix
+     * @param newPixelScaleRaw new raw surface pixel-scale
+     * @return {@code true} if pixel-scale has changed, otherwise {@code false}.
+     */
+    public static boolean setNewPixelScale(final float[] result,
+                                           final float[] prePixelScale, final float[] reqPixelScale,
+                                           final float[] minPixelScale, final float[] maxPixelScale,
+                                           final String DEBUG_PREFIX) {
+        final float resultX = clampPixelScale(reqPixelScale[0], minPixelScale[0], maxPixelScale[0]);
+        final float resultY = clampPixelScale(reqPixelScale[1], minPixelScale[1], maxPixelScale[1]);
+        final boolean changed = resultX != prePixelScale[0] || resultY != prePixelScale[1];
+        if( null != DEBUG_PREFIX ) {
+            System.err.println(DEBUG_PREFIX+".setNewPixelScale: pre["+prePixelScale[0]+", "+prePixelScale[1]+"], req["+
+                    reqPixelScale[0]+", "+reqPixelScale[1]+"], min["+
+                    minPixelScale[0]+", "+minPixelScale[1]+"], max["+
+                    maxPixelScale[0]+", "+maxPixelScale[1]+"] -> result["+
+                    resultX+", "+resultY+"], changed "+changed);
+        }
+        result[0] = resultX;
+        result[1] = resultY;
+        return changed;
+    }
 }
index d3439b5..cfcca7d 100644 (file)
@@ -42,7 +42,7 @@ import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
  * @see ProxySurface
  */
 public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface {
-  private final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+  private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
   private long surfaceHandle;
 
   /**
@@ -104,27 +104,23 @@ public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface
   /**
    * {@inheritDoc}
    * <p>
-   * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly.
+   * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(float[]) given pixelScale} directly.
    * </p>
    */
   @Override
   public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
-      pixelUnitsAndResult[0] /= hasPixelScale[0];
-      pixelUnitsAndResult[1] /= hasPixelScale[1];
-      return pixelUnitsAndResult;
+      return SurfaceScaleUtils.scaleInv(pixelUnitsAndResult, pixelUnitsAndResult, hasPixelScale);
   }
 
   /**
    * {@inheritDoc}
    * <p>
-   * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(int[]) given pixelScale} directly.
+   * {@link WrappedSurface}'s implementation uses the {@link #setSurfaceScale(float[]) given pixelScale} directly.
    * </p>
    */
   @Override
   public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
-      windowUnitsAndResult[0] *= hasPixelScale[0];
-      windowUnitsAndResult[1] *= hasPixelScale[1];
-      return windowUnitsAndResult;
+      return SurfaceScaleUtils.scale(windowUnitsAndResult, windowUnitsAndResult, hasPixelScale);
   }
 
   /**
@@ -147,25 +143,32 @@ public class WrappedSurface extends ProxySurfaceImpl implements ScalableSurface
    * </p>
    */
   @Override
-  public final void setSurfaceScale(final int[] pixelScale) {
-      hasPixelScale[0] = pixelScale[0];
-      hasPixelScale[1] = pixelScale[1];
+  public final boolean setSurfaceScale(final float[] pixelScale) {
+      final boolean changed = hasPixelScale[0] != pixelScale[0] || hasPixelScale[1] != pixelScale[1];
+      System.arraycopy(pixelScale, 0, hasPixelScale, 0, 2);
+      return changed;
   }
 
   @Override
-  public final int[] getRequestedSurfaceScale(final int[] result) {
+  public final float[] getRequestedSurfaceScale(final float[] result) {
       System.arraycopy(hasPixelScale, 0, result, 0, 2);
       return result;
   }
 
   @Override
-  public final int[] getCurrentSurfaceScale(final int[] result) {
+  public final float[] getCurrentSurfaceScale(final float[] result) {
       System.arraycopy(hasPixelScale, 0, result, 0, 2);
       return result;
   }
 
   @Override
-  public final int[] getNativeSurfaceScale(final int[] result) {
+  public float[] getMinimumSurfaceScale(final float[] result) {
+      System.arraycopy(hasPixelScale, 0, result, 0, 2);
+      return result;
+  }
+
+  @Override
+  public final float[] getMaximumSurfaceScale(final float[] result) {
       System.arraycopy(hasPixelScale, 0, result, 0, 2);
       return result;
   }
index 231a89c..4fd2b0d 100644 (file)
@@ -56,6 +56,7 @@ import javax.media.nativewindow.ToolkitLock;
 import jogamp.common.os.PlatformPropsImpl;
 import jogamp.nativewindow.Debug;
 import jogamp.nativewindow.NWJNILibLoader;
+import jogamp.nativewindow.macosx.OSXUtil;
 
 import com.jogamp.common.os.Platform;
 import com.jogamp.common.util.PropertyAccess;
@@ -93,6 +94,7 @@ public class JAWTUtil {
   private static final ToolkitLock jawtToolkitLock;
 
   private static final Method getScaleFactorMethod;
+  private static final Method getCGDisplayIDMethodOnOSX;
 
   private static class PrivilegedDataBlob1 {
     PrivilegedDataBlob1() {
@@ -101,6 +103,7 @@ public class JAWTUtil {
     Method sunToolkitAWTLockMethod;
     Method sunToolkitAWTUnlockMethod;
     Method getScaleFactorMethod;
+    Method getCGDisplayIDMethodOnOSX;
     boolean ok;
   }
 
@@ -321,6 +324,7 @@ public class JAWTUtil {
         hasSunToolkitAWTLock = false;
         // hasSunToolkitAWTLock = false;
         getScaleFactorMethod = null;
+        getCGDisplayIDMethodOnOSX = null;
     } else {
         // Non-headless case
         JAWTJNILibLoader.initSingleton(); // load libjawt.so
@@ -357,8 +361,13 @@ public class JAWTUtil {
                 }
                 try {
                     final GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
-                    d.getScaleFactorMethod = gd.getClass().getDeclaredMethod("getScaleFactor");
+                    final Class<?> gdClass = gd.getClass();
+                    d.getScaleFactorMethod = gdClass.getDeclaredMethod("getScaleFactor");
                     d.getScaleFactorMethod.setAccessible(true);
+                    if( Platform.OSType.MACOS == PlatformPropsImpl.OS_TYPE ) {
+                        d.getCGDisplayIDMethodOnOSX = gdClass.getDeclaredMethod("getCGDisplayID");
+                        d.getCGDisplayIDMethodOnOSX.setAccessible(true);
+                    }
                 } catch (final Throwable t) {}
                 return d;
             }
@@ -366,6 +375,7 @@ public class JAWTUtil {
         sunToolkitAWTLockMethod = pdb1.sunToolkitAWTLockMethod;
         sunToolkitAWTUnlockMethod = pdb1.sunToolkitAWTUnlockMethod;
         getScaleFactorMethod = pdb1.getScaleFactorMethod;
+        getCGDisplayIDMethodOnOSX = pdb1.getCGDisplayIDMethodOnOSX;
 
         boolean _hasSunToolkitAWTLock = false;
         if ( pdb1.ok ) {
@@ -545,20 +555,46 @@ public class JAWTUtil {
    * Note: Currently only supported on OSX since 1.7.0_40 for HiDPI retina displays
    * </p>
    * @param device the {@link GraphicsDevice} instance used to query the pixel scale
-   * @return the pixel scale factor
+   * @param minScale current and output min scale values
+   * @param maxScale current and output max scale values
+   * @return {@code true} if the given min and max scale values have changed, otherwise {@code false}.
    */
-  public static final int getPixelScale(final GraphicsDevice device) {
+  public static final boolean getPixelScale(final GraphicsDevice device, final float[] minScale, final float[] maxScale) {
+      // Shall we allow ]0..1[ minimum scale?
+      boolean changed = minScale[0] != 1f || minScale[1] != 1f;
+      minScale[0] = 1f;
+      minScale[1] = 1f;
+      float sx = 1f;
+      float sy = 1f;
       if( !SKIP_AWT_HIDPI ) {
+          if( null != getCGDisplayIDMethodOnOSX ) {
+              // OSX specific, preserving double type
+              try {
+                  final Object res = getCGDisplayIDMethodOnOSX.invoke(device);
+                  if (res instanceof Integer) {
+                      final int displayID = ((Integer)res).intValue();
+                      sx = (float) OSXUtil.GetPixelScaleByDisplayID(displayID);
+                      sy = sx;
+                  }
+              } catch (final Throwable t) {}
+          }
           if( null != getScaleFactorMethod ) {
+              // Generic (?)
               try {
                   final Object res = getScaleFactorMethod.invoke(device);
                   if (res instanceof Integer) {
-                      return ((Integer)res).intValue();
+                      sx = ((Integer)res).floatValue();
+                  } else if ( res instanceof Double) {
+                      sx = ((Double)res).floatValue();
                   }
+                  sy = sx;
               } catch (final Throwable t) {}
           }
       }
-      return 1;
+      changed = maxScale[0] != sx || maxScale[1] != sy;
+      maxScale[0] = sx;
+      maxScale[1] = sy;
+      return changed;
   }
 
   /**
@@ -574,20 +610,23 @@ public class JAWTUtil {
    * Note: Currently only supported on OSX since 1.7.0_40 for HiDPI retina displays
    * </p>
    * @param gc the {@link GraphicsConfiguration} instance used to query the pixel scale
-   * @return the pixel scale factor
+   * @param minScale current and output min scale values
+   * @param maxScale current and output max scale values
+   * @return {@code true} if the given min and max scale values have changed, otherwise {@code false}.
    */
-  public static final int getPixelScale(final GraphicsConfiguration gc) {
+  public static final boolean getPixelScale(final GraphicsConfiguration gc, final float[] minScale, final float[] maxScale) {
       final GraphicsDevice device = null != gc ? gc.getDevice() : null;
-      final int ps;
+      boolean changed;
       if( null == device ) {
-          ps = 0;
+          changed = minScale[0] != 1f || minScale[1] != 1f || maxScale[0] != 1f || maxScale[1] != 1f;
+          minScale[0] = 1f;
+          minScale[1] = 1f;
+          maxScale[0] = 1f;
+          maxScale[1] = 1f;
       } else {
-          ps = JAWTUtil.getPixelScale(device);
-      }
-      if( DEBUG ) {
-          System.err.println("JAWTUtil.updatePixelScale: Fetched "+ps);
+          changed = JAWTUtil.getPixelScale(device, minScale, maxScale);
       }
-      return ps;
+      return changed;
   }
 }
 
index fae8db5..1c6c412 100644 (file)
@@ -48,7 +48,6 @@ import java.security.PrivilegedAction;
 import javax.media.nativewindow.AbstractGraphicsConfiguration;
 import javax.media.nativewindow.Capabilities;
 import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.NativeWindow;
 import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.MutableSurface;
 import javax.media.nativewindow.util.Point;
@@ -116,13 +115,10 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
   }
 
   @Override
-  public void setSurfaceScale(final int[] pixelScale) {
+  public boolean setSurfaceScale(final float[] pixelScale) {
       super.setSurfaceScale(pixelScale);
-      if( 0 != getWindowHandle() ) { // locked at least once !
-          final int hadPixelScaleX = getPixelScaleX();
-          updatePixelScale();
-
-          if( hadPixelScaleX != getPixelScaleX() && 0 != getAttachedSurfaceLayer() ) {
+      if( 0 != getWindowHandle() && setReqPixelScale() ) { // locked at least once _and_ updated pixel-scale
+          if( 0 != getAttachedSurfaceLayer() ) {
               OSXUtil.RunOnMainThread(false, false, new Runnable() {
                   @Override
                   public void run() {
@@ -133,6 +129,9 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
                   }
               });
           }
+          return true;
+      } else {
+          return false;
       }
   }
 
index 9af74d9..7cd0439 100644 (file)
@@ -31,8 +31,6 @@ import javax.media.nativewindow.NativeWindowException;
 import javax.media.nativewindow.NativeWindowFactory;
 import javax.media.nativewindow.util.Insets;
 import javax.media.nativewindow.util.Point;
-import javax.media.nativewindow.util.Rectangle;
-import javax.media.nativewindow.util.RectangleImmutable;
 
 import com.jogamp.common.util.Function;
 import com.jogamp.common.util.FunctionTask;
@@ -109,64 +107,14 @@ public class OSXUtil implements ToolkitProperties {
       return (Insets) GetInsets0(windowOrView);
     }
 
-    /**
-     * Returns the pixel-scale of the NSScreen, with the highest
-     * {@link RectangleImmutable#coverage(RectangleImmutable) coverage} of the given rectangle in window units.
-     * <p>
-     * If no coverage is detected the pixel-scale of the first NSScreen is returned.
-     * </p>
-     * @param r arbitrary rectangle in window units
-     * @param screenIndexOut storage returning the native screen index containing the given rectangle
-     */
-    public static double GetPixelScale(final RectangleImmutable r, final int[] screenIndexOut) {
-        if( DEBUG ) {
-            System.err.printf("GetPixelScale covering %s%n", r.toString());
-        }
-        final int screenCount;
-        final RectangleImmutable[] screenBounds;
-        final double[] pixelScales;
-        {
-            final double[] sd = GetScreenData0();
-            if( 0 != sd.length % 5 ) {
-                throw new InternalError("GetScreenData0 didn't return multiple of 5 but "+sd.length);
-            }
-            screenCount = sd.length / 5;
-            screenBounds = new RectangleImmutable[screenCount];
-            pixelScales = new double[screenCount] ;
-            for(int i=0; i<screenCount; i++) {
-                final int j = i*5;
-                pixelScales[i] = sd[j+0];
-                screenBounds[i] = new Rectangle((int)sd[j+1], (int)sd[j+2], (int)sd[j+3], (int)sd[j+4]);
-                if( DEBUG ) {
-                    System.err.printf("GetPixelScale.Screen[%d]: scale %f, bounds[%f / %f  %f x %f]%n",
-                            i, pixelScales[i], sd[j+1], sd[j+2], sd[j+3], sd[j+4]);
-                }
-            }
-        }
-        double pixelScale = pixelScales[0];
-        screenIndexOut[0] = 0;
-        float maxCoverage = Float.MIN_VALUE;
-        for(int i=screenCount-1; i>=0; i--) {
-            final RectangleImmutable sb = screenBounds[i];
-            final float coverage = sb.coverage(r);
-            if( coverage > maxCoverage ) {
-                maxCoverage = coverage;
-                screenIndexOut[0] = i;
-                pixelScale = pixelScales[i];
-            }
-        }
-        if( DEBUG ) {
-            System.err.printf("GetPixelScale Result: screen %d, scale %f%n%n", screenIndexOut[0], pixelScale);
-        }
-        return pixelScale;
-    }
-
-    public static double GetPixelScale(final int screenIndex) {
+    public static double GetPixelScaleByScreenIdx(final int screenIndex) {
       return GetPixelScale0(screenIndex);
     }
-
+    public static double GetPixelScaleByDisplayID(final int displayID) {
+      return GetPixelScale1(displayID);
+    }
     public static double GetPixelScale(final long windowOrView) {
-      return GetPixelScale1(windowOrView);
+      return GetPixelScale2(windowOrView);
     }
 
     public static long CreateNSWindow(final int x, final int y, final int width, final int height) {
@@ -447,9 +395,9 @@ public class OSXUtil implements ToolkitProperties {
     private static native boolean isNSWindow0(long object);
     private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y);
     private static native Object GetInsets0(long windowOrView);
-    private static native double[] GetScreenData0();
     private static native double GetPixelScale0(int screenIndex);
-    private static native double GetPixelScale1(long windowOrView);
+    private static native double GetPixelScale1(int displayID);
+    private static native double GetPixelScale2(long windowOrView);
     private static native long CreateNSWindow0(int x, int y, int width, int height);
     private static native void DestroyNSWindow0(long nsWindow);
     private static native long GetNSView0(long nsWindow);
index 997bafb..c86025e 100644 (file)
@@ -138,12 +138,24 @@ Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused,
 }
 
 static CGDirectDisplayID OSXUtil_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
-    // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?!
+    // Mind: typedef uint32_t CGDirectDisplayID;
     NSDictionary * dict = [screen deviceDescription];
     NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"];
     // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size
     return (CGDirectDisplayID) [val integerValue];
 }
+static NSScreen * OSXUtil_getNSScreenByCGDirectDisplayID(CGDirectDisplayID displayID) {
+    NSArray *screens = [NSScreen screens];
+    int i;
+    for(i=[screens count]-1; i>=0; i--) {
+        NSScreen * screen = (NSScreen *) [screens objectAtIndex: i];
+        CGDirectDisplayID dID = OSXUtil_getCGDirectDisplayIDByNSScreen(screen);
+        if( dID == displayID ) {
+            return screen;
+        }
+    }
+    return (NSScreen *) [screens objectAtIndex: 0];
+}
 
 /*
  * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
@@ -249,87 +261,54 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetInsets0
     return res;
 }
 
-static CGDirectDisplayID GetCGDirectDisplayIDByNSScreen(NSScreen *screen) {
-    // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?!
-    NSDictionary * dict = [screen deviceDescription];
-    NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"];
-    // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size
-    return (CGDirectDisplayID) [val integerValue];
-}
-
 /*
  * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
- * Method:    GetScreenData0
- * Signature: ()[F
+ * Method:    GetPixelScale0
+ * Signature: (I)D
  */
-JNIEXPORT jdoubleArray JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenData0
-  (JNIEnv *env, jclass unused)
+JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale0
+  (JNIEnv *env, jclass unused, jint screen_idx)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
     CGFloat pixelScale;
-    CGDirectDisplayID display;
-    NSRect dBounds;
     NSScreen *screen;
     NSArray *screens = [NSScreen screens];
-    int sCount = [screens count];
-    jdouble res[sCount*5];
-    int i,j;
-
-    for(i=0; i<sCount; i++) {
-        j = i*5;
-        screen = (NSScreen *) [screens objectAtIndex: i];
+    if( screen_idx<0 || screen_idx>=[screens count] ) {
+        screen = NULL;
+        pixelScale = 1.0;
+    } else {
+        screen = (NSScreen *) [screens objectAtIndex: screen_idx];
         pixelScale = 1.0; // default
 NS_DURING
         // Available >= 10.7
         pixelScale = [screen backingScaleFactor]; // HiDPI scaling
 NS_HANDLER
 NS_ENDHANDLER
-        display = GetCGDirectDisplayIDByNSScreen(screen);
-        dBounds = CGDisplayBounds (display); // origin top-left
-        res[j+0] = (jdouble)pixelScale;
-        res[j+1] = (jdouble)dBounds.origin.x;
-        res[j+2] = (jdouble)dBounds.origin.y;
-        res[j+3] = (jdouble)dBounds.size.width;
-        res[j+4] = (jdouble)dBounds.size.height;
     }
-
-    jdoubleArray jniRes = (*env)->NewDoubleArray(env, sCount*5); // x,y,w,h,scale
-    if (jniRes == NULL) {
-        NativewindowCommon_throwNewRuntimeException(env, "Could not allocate double array of size %d", sCount*5);
-    }
-    (*env)->SetDoubleArrayRegion(env, jniRes, 0, sCount*5, res);
-
     [pool release];
 
-    return jniRes;
+    return (jdouble)pixelScale;
 }
 
 /*
  * Class:     Java_jogamp_nativewindow_macosx_OSXUtil
- * Method:    GetPixelScale0
+ * Method:    GetPixelScale1
  * Signature: (I)D
  */
-JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale0
-  (JNIEnv *env, jclass unused, jint screen_idx)
+JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale1
+  (JNIEnv *env, jclass unused, jint displayID)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
     CGFloat pixelScale;
-    NSScreen *screen;
-    NSArray *screens = [NSScreen screens];
-    if( screen_idx<0 || screen_idx>=[screens count] ) {
-        screen = NULL;
-        pixelScale = 0.0;
-    } else {
-        screen = (NSScreen *) [screens objectAtIndex: screen_idx];
-        pixelScale = 1.0; // default
+    NSScreen *screen =  OSXUtil_getNSScreenByCGDirectDisplayID((CGDirectDisplayID)displayID);
+    pixelScale = 1.0; // default
 NS_DURING
-        // Available >= 10.7
-        pixelScale = [screen backingScaleFactor]; // HiDPI scaling
+    // Available >= 10.7
+    pixelScale = [screen backingScaleFactor]; // HiDPI scaling
 NS_HANDLER
 NS_ENDHANDLER
-    }
     [pool release];
 
     return (jdouble)pixelScale;
@@ -340,7 +319,7 @@ NS_ENDHANDLER
  * Method:    GetPixelScale1
  * Signature: (J)D
  */
-JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale1
+JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetPixelScale2
   (JNIEnv *env, jclass unused, jlong winOrView)
 {
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
index 1261620..1a3222c 100644 (file)
@@ -30,6 +30,7 @@ package com.jogamp.newt;
 
 import java.util.List;
 
+import javax.media.nativewindow.ScalableSurface;
 import javax.media.nativewindow.util.DimensionImmutable;
 import javax.media.nativewindow.util.Rectangle;
 import javax.media.nativewindow.util.RectangleImmutable;
@@ -51,6 +52,7 @@ import com.jogamp.common.util.ArrayHashSet;
  *   <ul>
  *     <li>{@link MonitorMode} current mode</li>
  *     <li>{@link RectangleImmutable} viewport (rotated)</li>
+ *     <li>pixel-scale (rotated)</li>
  *   </ul></li>
  * </ul>
  * <p>
@@ -65,16 +67,31 @@ public abstract class MonitorDevice {
     protected final ArrayHashSet<MonitorMode> supportedModes; // FIXME: May need to support mutable mode, i.e. adding modes on the fly!
     protected MonitorMode currentMode;
     protected boolean modeChanged;
-    protected Rectangle viewportPU; // in pixel units
-    protected Rectangle viewportWU; // in window units
+    protected final float[] pixelScale;
+    protected final Rectangle viewportPU; // in pixel units
+    protected final Rectangle viewportWU; // in window units
 
-    protected MonitorDevice(final Screen screen, final int nativeId, final DimensionImmutable sizeMM, final Rectangle viewportPU, final Rectangle viewportWU, final MonitorMode currentMode, final ArrayHashSet<MonitorMode> supportedModes) {
+    /**
+     * @param screen associated {@link Screen}
+     * @param nativeId unique monitor device ID
+     * @param sizeMM size in millimeters
+     * @param currentMode
+     * @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}.
+     * @param viewportPU viewport in pixel-units
+     * @param viewportWU viewport in window-units
+     * @param supportedModes all supported {@link MonitorMode}s
+     */
+    protected MonitorDevice(final Screen screen, final int nativeId, final DimensionImmutable sizeMM,
+                            final MonitorMode currentMode,
+                            final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU,
+                            final ArrayHashSet<MonitorMode> supportedModes) {
         this.screen = screen;
         this.nativeId = nativeId;
         this.sizeMM = sizeMM;
         this.originalMode = currentMode;
         this.supportedModes = supportedModes;
         this.currentMode = currentMode;
+        this.pixelScale = null != pixelScale ? pixelScale : new float[] { 1.0f, 1.0f };
         this.viewportPU = viewportPU;
         this.viewportWU = viewportWU;
         this.modeChanged = false;
@@ -180,26 +197,40 @@ public abstract class MonitorDevice {
     }
 
     /**
-     * Returns the {@link RectangleImmutable rectangular} portion
+     * Returns the current {@link RectangleImmutable rectangular} portion
      * of the <b>rotated</b> virtual {@link Screen} size in pixel units
      * represented by this monitor, i.e. top-left origin and size.
-     * @see Screen
+     * @see #getPixelScale()
+     * @see Screen#getViewport()
      */
     public final RectangleImmutable getViewport() {
         return viewportPU;
     }
 
     /**
-     * Returns the {@link RectangleImmutable rectangular} portion
+     * Returns the current {@link RectangleImmutable rectangular} portion
      * of the <b>rotated</b> virtual {@link Screen} size in window units
      * represented by this monitor, i.e. top-left origin and size.
-     * @see Screen
+     * @see #getPixelScale()
+     * @see Screen#getViewportInWindowUnits()
      */
     public final RectangleImmutable getViewportInWindowUnits() {
         return viewportWU;
     }
 
     /**
+     * Returns the current <b>rotated</b> pixel-scale
+     * of this monitor, i.e. horizontal and vertical.
+     * @see #getViewportInWindowUnits()
+     * @see #getViewport()
+     * @see ScalableSurface#getMaximumSurfaceScale(float[])
+     */
+    public float[] getPixelScale(final float[] result) {
+        System.arraycopy(pixelScale, 0, result, 0, 2);
+        return result;
+    }
+
+    /**
      * Returns <code>true</code> if given screen coordinates in pixel units
      * are contained by this {@link #getViewport() viewport}, otherwise <code>false</code>.
      * @param x x-coord in pixel units
@@ -292,7 +323,8 @@ public abstract class MonitorDevice {
 
     @Override
     public String toString() {
-        return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, viewport "+viewportPU+ " [pixels], "+viewportWU+" [window], orig "+originalMode+", curr "+currentMode+
+        return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, pixelScale ["+pixelScale[0]+", "+pixelScale[1]+
+               "], viewport "+viewportPU+ " [pixels], "+viewportWU+" [window], orig "+originalMode+", curr "+currentMode+
                ", modeChanged "+modeChanged+", modeCount "+supportedModes.size()+"]";
     }
 }
index c4ca9a5..7b7937c 100644 (file)
@@ -273,7 +273,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
      * according to the {@link #getMainMonitor() main monitor}'s <i>current</i> {@link MonitorMode mode}'s
      * {@link SurfaceSize#getResolution() surface resolution}.
      * <p>
-     * Method takes the {@link #getCurrentSurfaceScale(int[]) current surface-scale} and {@link #getNativeSurfaceScale(int[]) native surface-scale}
+     * Method takes the {@link #getCurrentSurfaceScale(float[]) current surface-scale} and {@link #getMaximumSurfaceScale(float[]) native surface-scale}
      * into account, i.e.:
      * <pre>
      *    surfacePpMM = monitorPpMM * currentSurfaceScale / nativeSurfaceScale,
index e890bc6..b469492 100644 (file)
@@ -474,6 +474,13 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
                 }
                 jawtWindow = NewtFactoryAWT.getNativeWindow(NewtCanvasAWT.this, null != newtChild ? newtChild.getRequestedCapabilities() : null);
                 jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
+                // enforce initial lock on AWT-EDT, allowing acquisition of pixel-scale
+                jawtWindow.lockSurface();
+                try {
+                    // attachNewtChild sets surface scale!
+                } finally {
+                    jawtWindow.unlockSurface();
+                }
                 awtWindowClosingProtocol.addClosingListener();
                 componentAdded = true; // Bug 910
                 if(DEBUG) {
@@ -486,6 +493,25 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
             }
         }
     }
+    private final boolean updatePixelScale() {
+        if( jawtWindow.updatePixelScale(true) ) {
+            final Window cWin = newtChild;
+            final Window dWin = cWin.getDelegatedWindow();
+            if( dWin instanceof WindowImpl ) {
+                final float[] maxPixelScale = jawtWindow.getMaximumSurfaceScale(new float[2]);
+                final float[] minPixelScale = jawtWindow.getMinimumSurfaceScale(new float[2]);
+                ((WindowImpl)dWin).pixelScaleChangeNotify(minPixelScale, maxPixelScale, true);
+                // ((WindowImpl)dWin).sizeChangedNotify(true /* defer */, getWidth(), getHeight(), true /* force */);
+            } else {
+                final float[] reqPixelScale = jawtWindow.getRequestedSurfaceScale(new float[2]);
+                if( jawtWindow.setSurfaceScale(reqPixelScale) ) {
+                    // jawtWindow.getRequestedSurfaceScale(reqPixelScale);
+                }
+            }
+            return true;
+        }
+        return false;
+    }
 
     @Override
     public void removeNotify() {
@@ -588,7 +614,11 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
                     System.err.println("NewtCanvasAWT.reshape: "+x+"/"+y+" "+width+"x"+height);
                 }
                 if( validateComponent(true) ) {
-                    // newtChild.setSize(width, height);
+                    if( !printActive && updatePixelScale() ) {
+                        // NOP
+                    } else {
+                        // newtChild.setSize(width, height);
+                    }
                 }
             }
         }
@@ -877,18 +907,12 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
       }
       final int w = getWidth();
       final int h = getHeight();
-      final boolean isNValid = newtChild.isNativeValid();
       if(DEBUG) {
-          System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h+", isNValid "+isNValid);
+          System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h+", isNValid "+newtChild.isNativeValid());
       }
       newtChild.setVisible(false);
       newtChild.setSize(w, h);
-      final int[] reqSurfaceScale = new int[2];
-      if( isNValid ) {
-          newtChild.getCurrentSurfaceScale(reqSurfaceScale);
-      } else {
-          newtChild.getRequestedSurfaceScale(reqSurfaceScale);
-      }
+      final float[] reqSurfaceScale = newtChild.getRequestedSurfaceScale(new float[2]);
       jawtWindow.setSurfaceScale(reqSurfaceScale);
       newtChild.reparentWindow(jawtWindow, -1, -1, Window.REPARENT_HINT_BECOMES_VISIBLE);
       newtChild.addSurfaceUpdatedListener(jawtWindow);
index 2ba030f..0d286f2 100644 (file)
@@ -401,23 +401,28 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     }
 
     @Override
-    public final void setSurfaceScale(final int[] pixelScale) {
-        window.setSurfaceScale(pixelScale);
+    public final boolean setSurfaceScale(final float[] pixelScale) {
+        return window.setSurfaceScale(pixelScale);
     }
 
     @Override
-    public final int[] getRequestedSurfaceScale(final int[] result) {
+    public final float[] getRequestedSurfaceScale(final float[] result) {
         return window.getRequestedSurfaceScale(result);
     }
 
     @Override
-    public final int[] getCurrentSurfaceScale(final int[] result) {
+    public final float[] getCurrentSurfaceScale(final float[] result) {
         return window.getCurrentSurfaceScale(result);
     }
 
     @Override
-    public final int[] getNativeSurfaceScale(final int[] result) {
-        return window.getNativeSurfaceScale(result);
+    public final float[] getMinimumSurfaceScale(final float[] result) {
+        return window.getMinimumSurfaceScale(result);
+    }
+
+    @Override
+    public final float[] getMaximumSurfaceScale(final float[] result) {
+        return window.getMaximumSurfaceScale(result);
     }
 
     @Override
index 7230074..f1bd445 100644 (file)
@@ -28,6 +28,7 @@
 
 package jogamp.newt;
 
+import javax.media.nativewindow.ScalableSurface;
 import javax.media.nativewindow.util.DimensionImmutable;
 import javax.media.nativewindow.util.Rectangle;
 
@@ -38,8 +39,21 @@ import com.jogamp.newt.Screen;
 
 public class MonitorDeviceImpl extends MonitorDevice {
 
-    public MonitorDeviceImpl(final ScreenImpl screen, final int nativeId, final DimensionImmutable sizeMM, final Rectangle viewportPU, final Rectangle viewportWU, final MonitorMode currentMode, final ArrayHashSet<MonitorMode> supportedModes) {
-        super(screen, nativeId, sizeMM, viewportPU, viewportWU, currentMode, supportedModes);
+    /**
+     * @param screen associated {@link Screen}
+     * @param nativeId unique monitor device ID
+     * @param sizeMM size in millimeters
+     * @param currentMode
+     * @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}.
+     * @param viewportPU viewport in pixel-units
+     * @param viewportWU viewport in window-units
+     * @param supportedModes all supported {@link MonitorMode}s
+     */
+    public MonitorDeviceImpl(final ScreenImpl screen, final int nativeId, final DimensionImmutable sizeMM,
+                             final MonitorMode currentMode,
+                             final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU,
+                             final ArrayHashSet<MonitorMode> supportedModes) {
+        super(screen, nativeId, sizeMM, currentMode, pixelScale, viewportPU, viewportWU, supportedModes);
     }
 
     @Override
index 6e376ce..6ed3b23 100644 (file)
@@ -33,6 +33,7 @@ import com.jogamp.newt.MonitorDevice;
 import com.jogamp.newt.MonitorMode;
 
 import java.util.List;
+import javax.media.nativewindow.ScalableSurface;
 import javax.media.nativewindow.util.Dimension;
 import javax.media.nativewindow.util.DimensionImmutable;
 import javax.media.nativewindow.util.Rectangle;
@@ -256,14 +257,19 @@ public class MonitorModeProps {
      * <p>
      * Note: This variant only works for impl. w/ a unique mode key pair <i>modeId, rotation</i>.
      * </p>
-     * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
      * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
-     * @param modeProperties the input data
+     * @param screen the associated {@link ScreenImpl}
+     * @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}.
+     * @param monitorProperties the input data minus 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}.
      * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices},
      *         matching the input <code>modeProperties</code>, or null if input could not be processed.
      */
-    public static MonitorDevice streamInMonitorDevice(final int[] monitor_idx, final Cache cache, final ScreenImpl screen, final int[] monitorProperties, int offset) {
+    public static MonitorDevice streamInMonitorDevice(final Cache cache, final ScreenImpl screen,
+                                                      final float[] pixelScale,
+                                                      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) {
@@ -298,7 +304,7 @@ public class MonitorModeProps {
                 }
             }
         }
-        MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewportPU, viewportWU, currentMode, supportedModes);
+        MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, currentMode, pixelScale, viewportPU, viewportWU, supportedModes);
         if(null!=cache) {
             monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice);
         }
@@ -329,17 +335,23 @@ public class MonitorModeProps {
      * This variant expects <code>count</code> to be <code>{@link MIN_MONITOR_DEVICE_PROPERTIES} - 1 - {@link NUM_MONITOR_MODE_PROPERTIES}</code>,
      * due to lack of supported mode and current mode.
      * </p>
-     *
-     * @param mode_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
      * @param cache hash arrays of unique {@link MonitorMode} components and {@link MonitorDevice}s, allowing to avoid duplicates
-     * @param supportedModes pre-assembled list of supported {@link MonitorMode}s from cache.
+     * @param screen the associated {@link ScreenImpl}
      * @param currentMode pre-fetched current {@link MonitorMode}s from cache.
-     * @param modeProperties the input data minus supported modes!
+     * @param pixelScale pre-fetched current pixel-scale, maybe {@code null} for {@link ScalableSurface#IDENTITY_PIXELSCALE}.
+     * @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
+     * @param monitor_idx if not null, returns the index of resulting {@link MonitorDevice} within {@link Cache#monitorDevices}.
      * @return {@link MonitorDevice} of the identical (old or new) element in {@link Cache#monitorDevices},
      *         matching the input <code>modeProperties</code>, or null if input could not be processed.
      */
-    public static MonitorDevice streamInMonitorDevice(final int[] monitor_idx, final Cache cache, final ScreenImpl screen, final ArrayHashSet<MonitorMode> supportedModes, final MonitorMode currentMode, final int[] monitorProperties, int offset) {
+    public static MonitorDevice streamInMonitorDevice(final Cache cache, final ScreenImpl screen,
+                                                      final MonitorMode currentMode,
+                                                      final float[] pixelScale,
+                                                      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) {
@@ -356,7 +368,7 @@ 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++]);
-        MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, viewportPU, viewportWU, currentMode, supportedModes);
+        MonitorDevice monitorDevice = new MonitorDeviceImpl(screen, id, sizeMM, currentMode, pixelScale, viewportPU, viewportWU, supportedModes);
         if(null!=cache) {
             monitorDevice = cache.monitorDevices.getOrAdd(monitorDevice);
         }
index e73e153..c57f845 100644 (file)
@@ -364,8 +364,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(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, int[], int)}</li>
-     *   <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ScreenImpl, ArrayHashSet, int[], int)}</li>
+     *   <li>{@link MonitorModeProps#streamInMonitorDevice(jogamp.newt.MonitorModeProps.Cache, ScreenImpl, double[], int[], int, int[])}</li>
+     *   <li>{@link MonitorModeProps#streamInMonitorDevice(int[], jogamp.newt.MonitorModeProps.Cache, ArrayHashSet, int[], int, ScreenImpl)}</li>
      *   <li>{@link MonitorModeProps#streamInMonitorMode(int[], jogamp.newt.MonitorModeProps.Cache, int[], int)}</li>
      * </ul>
      * @param cache memory pool caching the result
@@ -373,6 +373,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
     protected abstract void collectNativeMonitorModesAndDevicesImpl(MonitorModeProps.Cache cache);
 
     protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor,
+                                                            final float[] pixelScale,
                                                             final Rectangle viewportPU, final Rectangle viewportWU) {
         return false;
     }
@@ -428,9 +429,14 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
         final List<MonitorDevice> monitors = getMonitorDevices();
         for(int i=monitors.size()-1; i>=0; i--) {
             final MonitorDeviceImpl monitor = (MonitorDeviceImpl) monitors.get(i);
-            final boolean viewportUpdated = updateNativeMonitorDeviceViewportImpl(monitor, monitor.getMutuableViewportPU(), monitor.getMutuableViewportWU());
+            final float[] pixelScale = monitor.getPixelScale(new float[2]);
+            final boolean viewportUpdated = updateNativeMonitorDeviceViewportImpl(monitor, pixelScale,
+                                                                                  monitor.getMutuableViewportPU(),
+                                                                                  monitor.getMutuableViewportWU());
             if( DEBUG ) {
-                System.err.println("Screen.updateMonitorViewport["+i+"] @  "+Thread.currentThread().getName()+": updated: "+viewportUpdated+", PU "+monitor.getViewport()+", WU "+monitor.getViewportInWindowUnits());
+                System.err.println("Screen.updateMonitorViewport["+i+"] @  "+Thread.currentThread().getName()+": updated: "+viewportUpdated+
+                                   ", PU "+monitor.getViewport()+", WU "+monitor.getViewportInWindowUnits()+
+                                   ", pixelScale ["+pixelScale[0]+", "+pixelScale[1]+"]");
             }
         }
     }
@@ -510,7 +516,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
         if( MonitorModeProps.MIN_MONITOR_DEVICE_PROPERTIES != i ) {
             throw new InternalError("XX");
         }
-        return MonitorModeProps.streamInMonitorDevice(null, cache, this, props, 0);
+        return MonitorModeProps.streamInMonitorDevice(cache, this, null, props, 0, null);
     }
 
     /**
index 0c4dcd1..2230acd 100644 (file)
@@ -154,9 +154,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     private volatile boolean hasFocus = false;
     private volatile int pixWidth = 128, pixHeight = 128; // client-area size w/o insets in pixel units, default: may be overwritten by user
     private volatile int winWidth = 128, winHeight = 128; // client-area size w/o insets in window units, default: may be overwritten by user
-    protected final int[] nativePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-    protected final int[] hasPixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-    protected final int[] reqPixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+    protected final float[] minPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+    protected final float[] maxPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+    protected final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+    protected final float[] reqPixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
 
     private volatile int x = 64, y = 64; // client-area pos w/o insets in window units
     private volatile Insets insets = new Insets(); // insets of decoration (if top-level && decorated)
@@ -1087,8 +1088,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
     @Override
     public final void setSurfaceSize(final int pixelWidth, final int pixelHeight) {
-        // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology
-        setSize(pixelWidth / getPixelScaleX(), pixelHeight / getPixelScaleY());
+        setSize( SurfaceScaleUtils.scaleInv(pixelWidth, getPixelScaleX()),
+                 SurfaceScaleUtils.scaleInv(pixelHeight, getPixelScaleY()) );
     }
     @Override
     public final void setTopLevelSize(final int width, final int height) {
@@ -1181,8 +1182,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 parentWindowHandle = 0;
                 hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
                 hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
-                nativePixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
-                nativePixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+                minPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+                minPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
+                maxPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
+                maxPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
 
                 _lock.unlock();
             }
@@ -1926,16 +1929,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     @Override
     public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
-        pixelUnitsAndResult[0] /= getPixelScaleX();
-        pixelUnitsAndResult[1] /= getPixelScaleY();
-        return pixelUnitsAndResult;
+        return SurfaceScaleUtils.scaleInv(pixelUnitsAndResult, pixelUnitsAndResult, hasPixelScale);
     }
 
     @Override
     public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
-        windowUnitsAndResult[0] *= getPixelScaleX();
-        windowUnitsAndResult[1] *= getPixelScaleY();
-        return windowUnitsAndResult;
+        return SurfaceScaleUtils.scale(windowUnitsAndResult, windowUnitsAndResult, hasPixelScale);
     }
 
     protected final Point convertToWindowUnits(final Point pixelUnitsAndResult) {
@@ -1947,43 +1946,50 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
 
     /** HiDPI: We currently base scaling of window units to pixel units on an integer scale factor per component. */
-    protected final int getPixelScaleX() {
+    protected final float getPixelScaleX() {
         return hasPixelScale[0];
     }
 
     /** HiDPI: We currently base scaling of window units to pixel units on an integer scale factor per component. */
-    protected final int getPixelScaleY() {
+    protected final float getPixelScaleY() {
         return hasPixelScale[1];
     }
 
     @Override
-    public void setSurfaceScale(final int[] pixelScale) {
-        SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getSimpleName() : null);
+    public boolean setSurfaceScale(final float[] pixelScale) {
+        System.arraycopy(pixelScale, 0, reqPixelScale, 0, 2);
+        return false;
     }
 
     @Override
-    public final int[] getRequestedSurfaceScale(final int[] result) {
+    public final float[] getRequestedSurfaceScale(final float[] result) {
         System.arraycopy(reqPixelScale, 0, result, 0, 2);
         return result;
     }
 
     @Override
-    public final int[] getCurrentSurfaceScale(final int[] result) {
+    public final float[] getCurrentSurfaceScale(final float[] result) {
         System.arraycopy(hasPixelScale, 0, result, 0, 2);
         return result;
     }
 
     @Override
-    public final int[] getNativeSurfaceScale(final int[] result) {
-        System.arraycopy(nativePixelScale, 0, result, 0, 2);
+    public final float[] getMinimumSurfaceScale(final float[] result) {
+        System.arraycopy(minPixelScale, 0, result, 0, 2);
+        return result;
+    }
+
+    @Override
+    public final float[] getMaximumSurfaceScale(final float[] result) {
+        System.arraycopy(maxPixelScale, 0, result, 0, 2);
         return result;
     }
 
     @Override
     public final float[] getPixelsPerMM(final float[] ppmmStore) {
         getMainMonitor().getPixelsPerMM(ppmmStore);
-        ppmmStore[0] *= (float)hasPixelScale[0] / (float)nativePixelScale[0];
-        ppmmStore[1] *= (float)hasPixelScale[1] / (float)nativePixelScale[1];
+        ppmmStore[0] *= hasPixelScale[0] / maxPixelScale[0];
+        ppmmStore[1] *= hasPixelScale[1] / maxPixelScale[1];
         return ppmmStore;
     }
 
@@ -2004,8 +2010,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
      * and {@link #pixWidth} and {@link #pixHeight} in pixel units according to {@link #convertToPixelUnits(int[])}.
      */
     protected final void defineSize(final int winWidth, final int winHeight) {
-        final int pixWidth = winWidth * getPixelScaleX();   // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology
-        final int pixHeight = winHeight * getPixelScaleY();
+        final int pixWidth = SurfaceScaleUtils.scale(winWidth, getPixelScaleX());   // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology
+        final int pixHeight = SurfaceScaleUtils.scale(winHeight, getPixelScaleY());
+
         if(DEBUG_IMPLEMENTATION) {
             System.err.println("defineSize: win["+this.winWidth+"x"+this.winHeight+" -> "+winWidth+"x"+winHeight+
                                "], pixel["+this.pixWidth+"x"+this.pixHeight+" -> "+pixWidth+"x"+pixHeight+"]");
@@ -2631,13 +2638,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             // special repaint treatment
             case WindowEvent.EVENT_WINDOW_REPAINT:
                 // queue repaint event in case window is locked, ie in operation
-                if( null != windowLock.getOwner() ) {
+                if( windowLock.isLockedByOtherThread() ) {
                     // make sure only one repaint event is queued
                     if(!repaintQueued) {
                         repaintQueued=true;
                         final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen();
                         if(DEBUG_IMPLEMENTATION) {
-                            System.err.println("Window.consumeEvent: REPAINT "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
+                            System.err.println("Window.consumeEvent: REPAINT [me "+Thread.currentThread().getName()+", owner "+windowLock.getOwner()+"] - queued "+e+", discard-to "+discardTO);
                             // ExceptionUtils.dumpStackTrace(System.err);
                         }
                         return discardTO; // discardTO:=true -> consumed
@@ -2650,10 +2657,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             // common treatment
             case WindowEvent.EVENT_WINDOW_RESIZED:
                 // queue event in case window is locked, ie in operation
-                if( null != windowLock.getOwner() ) {
+                if( windowLock.isLockedByOtherThread() ) {
                     final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen();
                     if(DEBUG_IMPLEMENTATION) {
-                        System.err.println("Window.consumeEvent: RESIZED "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO);
+                        System.err.println("Window.consumeEvent: RESIZED [me "+Thread.currentThread().getName()+", owner "+windowLock.getOwner()+"] - queued "+e+", discard-to "+discardTO);
                         // ExceptionUtils.dumpStackTrace(System.err);
                     }
                     return discardTO; // discardTO:=true -> consumed
@@ -3756,6 +3763,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
+    /**
+     * Notify to update the pixel-scale values.
+     * @param minPixelScale
+     * @param maxPixelScale
+     * @param reset if {@code true} {@link #setSurfaceScale(float[]) reset pixel-scale} w/ {@link #getRequestedSurfaceScale(float[]) requested values}
+     *        value to reflect the new minimum and maximum values.
+     */
+    public final void pixelScaleChangeNotify(final float[] minPixelScale, final float[] maxPixelScale, final boolean reset) {
+        System.arraycopy(minPixelScale, 0, this.minPixelScale, 0, 2);
+        System.arraycopy(maxPixelScale, 0, this.maxPixelScale, 0, 2);
+        if( reset ) {
+            setSurfaceScale(reqPixelScale);
+        }
+    }
+
     /** Triggered by implementation's WM events to update the client-area size in window units w/o insets/decorations. */
     protected void sizeChanged(final boolean defer, final int newWidth, final int newHeight, final boolean force) {
         if(force || getWidth() != newWidth || getHeight() != newHeight) {
index b28cdcb..59688cd 100644 (file)
@@ -113,7 +113,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(null, cache, this, cache.monitorModes, currentMode, props, 0);
+        MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null);
     }
 
     @Override
index eccdd63..76ae267 100644 (file)
@@ -69,8 +69,8 @@ public class AWTCanvas extends Canvas {
   private final UpstreamScalable upstreamScale;
 
   public static interface UpstreamScalable {
-      int[] getReqPixelScale();
-      void setHasPixelScale(final int[] pixelScale);
+      float[] getReqPixelScale();
+      void setHasPixelScale(final float[] pixelScale);
   }
 
   private boolean displayConfigChanged=false;
@@ -148,7 +148,7 @@ public class AWTCanvas extends Canvas {
         // trigger initialization cycle
         jawtWindow.setSurfaceScale(upstreamScale.getReqPixelScale() );
         jawtWindow.lockSurface();
-        upstreamScale.setHasPixelScale(jawtWindow.getCurrentSurfaceScale(new int[2]));
+        upstreamScale.setHasPixelScale(jawtWindow.getCurrentSurfaceScale(new float[2]));
         jawtWindow.unlockSurface();
     }
 
index 57948cf..eb92e0d 100644 (file)
@@ -119,7 +119,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(null, cache, this, cache.monitorModes, currentMode, props, 0);
+        MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null);
     }
 
     @Override
index 06dcb8f..2ccc8d7 100644 (file)
@@ -100,12 +100,12 @@ public class WindowDriver extends WindowImpl {
 
     private final AWTCanvas.UpstreamScalable upstreamScalable = new AWTCanvas.UpstreamScalable() {
         @Override
-        public int[] getReqPixelScale() {
+        public float[] getReqPixelScale() {
             return WindowDriver.this.reqPixelScale;
         }
 
         @Override
-        public void setHasPixelScale(final int[] pixelScale) {
+        public void setHasPixelScale(final float[] pixelScale) {
             System.arraycopy(pixelScale, 0, WindowDriver.this.hasPixelScale, 0, 2);
         }
     };
index 2cd4731..f3ac3e8 100644 (file)
@@ -94,7 +94,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(null, cache, this, cache.monitorModes, currentMode, props, 0);
+        MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null);
     }
 
     @Override
index 64cae75..bc1c19f 100644 (file)
@@ -87,7 +87,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(null, cache, this, cache.monitorModes, currentMode, props, 0);
+        MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null);
     }
 
     @Override
index 2ce835c..36a95dc 100644 (file)
@@ -96,7 +96,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(null, cache, this, cache.monitorModes, currentMode, props, 0);
+        MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null);
     }
 
     @Override
index d411356..42659b1 100644 (file)
@@ -92,7 +92,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(null, cache, this, cache.monitorModes, currentMode, props, 0);
+        MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, cache.monitorModes, props, 0, null);
     }
 
     @Override
index 5f458e2..7c4fa56 100644 (file)
@@ -77,7 +77,7 @@ public class ScreenDriver extends ScreenImpl {
     private class CrtProps {
         CrtProps() {
             count = getMonitorCount0();
-            pixelScaleArray = new int[count];
+            pixelScaleArray = new float[count];
             propsOrigArray = new int[count][];
             propsFixedArray = new int[count][];
 
@@ -85,8 +85,8 @@ public class ScreenDriver extends ScreenImpl {
             // Gather whole topology of monitors (NSScreens)
             //
             for(int crtIdx=0; crtIdx<count; crtIdx++) {
-                final float pixelScaleRaw = (float) OSXUtil.GetPixelScale(crtIdx);
-                pixelScaleArray[crtIdx] = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1 : (int)pixelScaleRaw;
+                final float pixelScaleRaw = (float)OSXUtil.GetPixelScaleByScreenIdx(crtIdx);
+                pixelScaleArray[crtIdx] = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1.0f : pixelScaleRaw;
                 propsOrigArray[crtIdx] = getMonitorProps0(crtIdx);
                 if ( null == propsOrigArray[crtIdx] ) {
                     throw new InternalError("Could not gather device props "+crtIdx+"/"+count);
@@ -105,7 +105,7 @@ public class ScreenDriver extends ScreenImpl {
                 final int[] thisMonitorProps = propsFixedArray[crtIdx];
                 final int x = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+0];
                 final int y = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+1];
-                final int thisPixelScale = pixelScaleArray[crtIdx];
+                final float thisPixelScale = pixelScaleArray[crtIdx];
                 thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+2] *= thisPixelScale; // fix width
                 thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+3] *= thisPixelScale; // fix height
                 if( 0 != x ) {
@@ -129,7 +129,7 @@ public class ScreenDriver extends ScreenImpl {
             }
         }
         final int count;
-        final int[] pixelScaleArray;
+        final float[] pixelScaleArray;
         final int[][] propsOrigArray;
         final int[][] propsFixedArray;
     }
@@ -167,12 +167,15 @@ public class ScreenDriver extends ScreenImpl {
                 throw new InternalError("Could not gather current mode of device "+crtIdx+"/"+crtProps.count+", but gathered "+modeIdx+" modes");
             }
             // merge monitor-props + supported modes
-            MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, crtProps.propsFixedArray[crtIdx], 0);
+            final float pixelScale = crtProps.pixelScaleArray[crtIdx];
+            MonitorModeProps.streamInMonitorDevice(cache, this, currentMode,
+                                                   new float[] { pixelScale, pixelScale },
+                                                   supportedModes, crtProps.propsFixedArray[crtIdx], 0, null);
         }
     }
 
     @Override
-    protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final Rectangle viewportPU, final Rectangle viewportWU) {
+    protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU) {
         final CrtProps crtProps = new CrtProps();
         final int crtIdx = monitor.getId();
         if( 0 > crtIdx || crtIdx >= crtProps.count ) {
@@ -182,6 +185,9 @@ public class ScreenDriver extends ScreenImpl {
         int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT;
         viewportPU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]);
         viewportWU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]);
+        final float _pixelScale = crtProps.pixelScaleArray[crtIdx];
+        pixelScale[0] = _pixelScale;
+        pixelScale[1] = _pixelScale;
         return true;
     }
 
index c0f7d38..a57bb5a 100644 (file)
@@ -67,20 +67,26 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
     public WindowDriver() {
     }
 
-    private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final float newPixelScaleRaw, final float nativePixelScaleRaw) {
-        final int[] newPixelScale = new int[2];
+    private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final boolean deferOffThread,
+                                     final float newPixelScaleRaw, final float maxPixelScaleRaw) {
+        final float[] newPixelScale = new float[2];
         {
-            final int _newPixelScale = FloatUtil.isZero(newPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : (int) newPixelScaleRaw;
+            final float _newPixelScale = FloatUtil.isZero(newPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : newPixelScaleRaw;
             newPixelScale[0]= _newPixelScale;
             newPixelScale[1]= _newPixelScale;
-            final int _nativePixelScale = FloatUtil.isZero(nativePixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : (int) nativePixelScaleRaw;
-            nativePixelScale[0]= _nativePixelScale;
-            nativePixelScale[1]= _nativePixelScale;
+            final float _maxPixelScale = FloatUtil.isZero(maxPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : maxPixelScaleRaw;
+            maxPixelScale[0]= _maxPixelScale;
+            maxPixelScale[1]= _maxPixelScale;
         }
+        // We keep minPixelScale at [1f, 1f]!
 
-        if( SurfaceScaleUtils.computePixelScale(hasPixelScale, hasPixelScale, reqPixelScale, newPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
+        if( SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, newPixelScale, minPixelScale, maxPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
             if( sendEvent ) {
-                super.sizeChanged(defer, getWidth(), getHeight(), true);
+                if( deferOffThread ) {
+                    superSizeChangedOffThread(defer, getWidth(), getHeight(), true);
+                } else {
+                    super.sizeChanged(defer, getWidth(), getHeight(), true);
+                }
             } else {
                 defineSize(getWidth(), getHeight());
             }
@@ -91,34 +97,34 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
     }
 
     private boolean updatePixelScaleByScreenIdx(final boolean sendEvent) {
-        final float nativePixelScaleRaw = (float) OSXUtil.GetPixelScale(getScreen().getIndex());
+        final float maxPixelScaleRaw = (float) OSXUtil.GetPixelScaleByScreenIdx(getScreen().getIndex());
         if( DEBUG_IMPLEMENTATION ) {
-            System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+", "+nativePixelScaleRaw+" (native)");
+            System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+", "+maxPixelScaleRaw+" (max)");
         }
-        return updatePixelScale(sendEvent, true /* defer */, nativePixelScaleRaw, nativePixelScaleRaw);
+        return updatePixelScale(sendEvent, true /* defer */, false /*offthread */, maxPixelScaleRaw, maxPixelScaleRaw);
     }
 
     private boolean updatePixelScaleByWindowHandle(final boolean sendEvent) {
         final long handle = getWindowHandle();
         if( 0 != handle ) {
-            final float nativePixelScaleRaw = (float)OSXUtil.GetPixelScale(handle);
+            final float maxPixelScaleRaw = (float)OSXUtil.GetPixelScale(handle);
             if( DEBUG_IMPLEMENTATION ) {
-                System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+", "+nativePixelScaleRaw+" (native)");
+                System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+", "+maxPixelScaleRaw+" (max)");
             }
-            return updatePixelScale(sendEvent, true /* defer */, nativePixelScaleRaw, nativePixelScaleRaw);
+            return updatePixelScale(sendEvent, true /* defer */, false /*offthread */, maxPixelScaleRaw, maxPixelScaleRaw);
         } else {
             return false;
         }
     }
 
     /** Called from native code */
-    protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw, final float nativePixelScaleRaw) {
+    protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw, final float maxPixelScaleRaw) {
         final long handle = getWindowHandle();
         if( DEBUG_IMPLEMENTATION ) {
-            System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (raw), "+nativePixelScaleRaw+" (native), drop "+(0==handle));
+            System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (new), "+maxPixelScaleRaw+" (max), drop "+(0==handle));
         }
         if( 0 != handle ) {
-            updatePixelScale(true /* sendEvent*/, defer, newPixelScaleRaw, nativePixelScaleRaw);
+            updatePixelScale(true /* sendEvent*/, defer, true /*offthread */, newPixelScaleRaw, maxPixelScaleRaw);
         }
     }
 
@@ -139,44 +145,47 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
     }
 
     @Override
-    public final void setSurfaceScale(final int[] pixelScale) {
-        SurfaceScaleUtils.validateReqPixelScale(reqPixelScale, pixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null);
+    public final boolean setSurfaceScale(final float[] pixelScale) {
+        super.setSurfaceScale(pixelScale);
 
-        final int[] resPixelScale;
+        boolean changed = false;
         if( isNativeValid() ) {
             if( isOffscreenInstance ) {
                 final NativeWindow pWin = getParent();
                 if( pWin instanceof ScalableSurface ) {
                     final ScalableSurface sSurf = (ScalableSurface)pWin;
                     sSurf.setSurfaceScale(reqPixelScale);
-                    final int[] pPixelScale = sSurf.getCurrentSurfaceScale(new int[2]);
-                    sSurf.getNativeSurfaceScale(nativePixelScale);
-                    updatePixelScale(true /* sendEvent */, true /* defer */, pPixelScale[0], nativePixelScale[0]); // HiDPI: uniformPixelScale
+                    sSurf.getMaximumSurfaceScale(maxPixelScale);
+                    sSurf.getMinimumSurfaceScale(minPixelScale);
+                    final float[] pPixelScale = sSurf.getCurrentSurfaceScale(new float[2]);
+                    changed = updatePixelScale(true /* sendEvent */, true /* defer */, true /*offthread */, pPixelScale[0], maxPixelScale[0]); // HiDPI: uniformPixelScale
                 } else {
                     // just notify updated pixelScale if offscreen
-                    SurfaceScaleUtils.replaceAutoMaxWithPlatformMax(reqPixelScale);
-                    updatePixelScale(true /* sendEvent */, true /* defer */, reqPixelScale[0], nativePixelScale[0]); // HiDPI: uniformPixelScale
+                    changed = updatePixelScale(true /* sendEvent */, true /* defer */, true /*offthread */, reqPixelScale[0], maxPixelScale[0]); // HiDPI: uniformPixelScale
                 }
             } else {
-                // set pixelScale in native code, will issue an update PixelScale
-                OSXUtil.RunOnMainThread(true, false, new Runnable() {
-                    @Override
-                    public void run() {
-                        setPixelScale0(getWindowHandle(), surfaceHandle, reqPixelScale[0]); // HiDPI: uniformPixelScale
-                    }
-                } );
+                // set pixelScale in native code, will issue an update updatePixelScale(..)
+                // hence we pre-query whether pixel-scale will change, without affecting current state 'hasPixelScale'!
+                final float[] _hasPixelScale = new float[2];
+                System.arraycopy(hasPixelScale, 0, _hasPixelScale, 0, 2);
+                if( SurfaceScaleUtils.setNewPixelScale(_hasPixelScale, _hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
+                    OSXUtil.RunOnMainThread(true, false, new Runnable() {
+                        @Override
+                        public void run() {
+                            setPixelScale0(getWindowHandle(), surfaceHandle, _hasPixelScale[0]); // HiDPI: uniformPixelScale
+                        }
+                    } );
+                    changed = true;
+                }
             }
-            resPixelScale = hasPixelScale;
-        } else {
-            hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
-            hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
-            resPixelScale = reqPixelScale;
         }
         if( DEBUG_IMPLEMENTATION ) {
-            System.err.println("WindowDriver.setPixelScale: "+pixelScale[0]+"x"+pixelScale[1]+" (req) -> "+
-                                reqPixelScale[0]+"x"+reqPixelScale[1]+" (validated) -> "+
-                                resPixelScale[0]+"x"+resPixelScale[1]+" (result) - realized "+isNativeValid());
+            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
@@ -360,13 +369,23 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                     System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" ->  "+p0S+" screen-client-pos");
                 }
                 OSXUtil.RunOnMainThread(false, false, new Runnable() {
-                        @Override
-                        public void run() {
-                            setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
-                        } } );
+                    @Override
+                    public void run() {
+                        setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
+                    } } );
             }
         }
-        super.sizeChanged(defer, newWidth, newHeight, force);
+        superSizeChangedOffThread(defer, newWidth, newHeight, force);
+    }
+    private void superSizeChangedOffThread(final boolean defer, final int newWidth, final int newHeight, final boolean force) {
+        if( defer ) {
+            new Thread() {
+                public void run() {
+                    WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force);
+                } }.start();
+        } else {
+            WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force);
+        }
     }
 
     @Override
@@ -556,14 +575,18 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
     @Override
     protected void warpPointerImpl(final int x, final int y) {
         if( !isOffscreenInstance ) {
-            warpPointer0(getWindowHandle(), x / getPixelScaleX(), y / getPixelScaleY());
+            warpPointer0(getWindowHandle(),
+                         SurfaceScaleUtils.scaleInv(x, getPixelScaleX()),
+                         SurfaceScaleUtils.scaleInv(y, getPixelScaleY()));
         } // else may need offscreen solution ? FIXME
     }
 
     @Override
     protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
                                       final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
-        super.doMouseEvent(enqueue, wait, eventType, modifiers, x * getPixelScaleX(), y * getPixelScaleY(), button, rotationXYZ, rotationScale);
+        super.doMouseEvent(enqueue, wait, eventType, modifiers,
+                           SurfaceScaleUtils.scale(x, getPixelScaleX()),
+                           SurfaceScaleUtils.scale(y, getPixelScaleY()), button, rotationXYZ, rotationScale);
     }
 
     @Override
index 38acd03..79ba623 100644 (file)
@@ -106,7 +106,7 @@ public class ScreenDriver extends ScreenImpl {
                 if ( null != currentMode ) { // enabled
                     final int[] monitorProps = getMonitorDevice0(adapterName, crtIdx);
                     // merge monitor-props + supported modes
-                    MonitorModeProps.streamInMonitorDevice(null, cache, this, supportedModes, currentMode, monitorProps, 0);
+                    MonitorModeProps.streamInMonitorDevice(cache, this, currentMode, null, supportedModes, monitorProps, 0, null);
 
                     // next monitor, 1st mode
                     supportedModes= new ArrayHashSet<MonitorMode>();
@@ -118,7 +118,7 @@ public class ScreenDriver extends ScreenImpl {
     }
 
     @Override
-    protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final Rectangle viewportPU, final Rectangle viewportWU) {
+    protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU) {
         final String adapterName = getAdapterName(monitor.getId());
         if( null != adapterName ) {
             final String activeMonitorName = getActiveMonitorName(adapterName, 0);
index f736174..1ec91dc 100644 (file)
@@ -152,7 +152,7 @@ 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(null, cache, this, monitorProps, 0);
+                                MonitorModeProps.streamInMonitorDevice(cache, this, null, monitorProps, 0, null);
                             }
                         }
                     }
@@ -166,7 +166,7 @@ public class ScreenDriver extends ScreenImpl {
     }
 
     @Override
-    protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final Rectangle viewportPU, final Rectangle viewportWU) {
+    protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU) {
         final AbstractGraphicsDevice device = getDisplay().getGraphicsDevice();
         device.lock();
         try {
index 2bd11da..1dbe2b7 100644 (file)
@@ -420,7 +420,7 @@ NS_ENDHANDLER
 
 
 CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) {
-    // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?!
+    // Mind: typedef uint32_t CGDirectDisplayID;
     NSDictionary * dict = [screen deviceDescription];
     NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"];
     // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size
index caf9e54..7b3df39 100644 (file)
@@ -784,11 +784,21 @@ static jmethodID windowRepaintID = NULL;
     [super viewDidChangeBackingProperties];
 
     // HiDPI scaling
-    BOOL useHiDPI = [self wantsBestResolutionOpenGLSurface];
-    CGFloat pixelScaleNative = [[self window] backingScaleFactor];
-    CGFloat pixelScaleUse = useHiDPI ? pixelScaleNative : 1.0;
-    DBG_PRINT("viewDidChangeBackingProperties: PixelScale: HiDPI %d, native %f -> use %f\n", useHiDPI, (float)pixelScaleNative, (float)pixelScaleUse);
-    [[self layer] setContentsScale: pixelScaleUse];
+    BOOL useHiDPI = false;
+    CGFloat maxPixelScale = 1.0;
+    CGFloat winPixelScale = 1.0;
+    NSWindow* window = [self window];
+    NSScreen* screen = [window screen];
+NS_DURING
+    maxPixelScale = [screen backingScaleFactor];
+    useHiDPI = [self wantsBestResolutionOpenGLSurface];
+    if( useHiDPI ) {
+        winPixelScale = [window backingScaleFactor];
+    }
+NS_HANDLER
+NS_ENDHANDLER
+    DBG_PRINT("viewDidChangeBackingProperties: PixelScale: HiDPI %d, max %f, window %f\n", useHiDPI, (float)maxPixelScale, (float)winPixelScale);
+    [[self layer] setContentsScale: winPixelScale];
 
     if (javaWindowObject == NULL) {
         DBG_PRINT("viewDidChangeBackingProperties: null javaWindowObject\n");
@@ -801,7 +811,7 @@ static jmethodID windowRepaintID = NULL;
         return;
     }
 
-    (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, JNI_TRUE, (jfloat)pixelScaleUse, (jfloat)pixelScaleNative); // defer 
+    (*env)->CallVoidMethod(env, javaWindowObject, updatePixelScaleID, JNI_TRUE, (jfloat)winPixelScale, (jfloat)maxPixelScale); // defer 
 
     // detaching thread not required - daemon
     // NewtCommon_ReleaseJNIEnv(shallBeDetached);
index 685e3bd..db838fe 100644 (file)
@@ -7,7 +7,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import javax.media.nativewindow.util.Dimension;
 import javax.media.opengl.GL;
 import javax.media.opengl.GL2ES2;
 import javax.media.opengl.GLAnimatorControl;
@@ -672,7 +671,7 @@ public class GPUUISceneGLListener0A implements GLEventListener {
             dpiH = surfacePixelsPerMM[1]*25.4f;
             System.err.println("Monitor detected: "+mm);
             System.err.println("Monitor dpi: "+monitorDpiH);
-            System.err.println("Surface scale: native "+new Dimension(upWin.getNativeSurfaceScale(new int[2]))+", current "+new Dimension(upWin.getCurrentSurfaceScale(new int[2])));
+            System.err.println("Surface scale: native "+Arrays.toString(upWin.getMaximumSurfaceScale(new float[2]))+", current "+Arrays.toString(upWin.getCurrentSurfaceScale(new float[2])));
             System.err.println("Surface dpi: "+dpiH);
         } else {
             System.err.println("Using default DPI of "+dpiH);
index 274fbea..f70f178 100644 (file)
@@ -30,7 +30,7 @@ public class GPUUISceneNewtCanvasAWTDemo {
     static boolean GraphMSAAMode = false;
     static float GraphAutoMode = GPUUISceneGLListener0A.DefaultNoAADPIThreshold;
 
-    static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+    static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
 
     static void setComponentSize(final Component comp, final DimensionImmutable new_sz) {
         try {
@@ -91,7 +91,7 @@ public class GPUUISceneNewtCanvasAWTDemo {
                     y = MiscUtils.atoi(args[i], y);
                 } else if(args[i].equals("-pixelScale")) {
                     i++;
-                    final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+                    final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]);
                     reqSurfacePixelScale[0] = pS;
                     reqSurfacePixelScale[1] = pS;
                 } else if(args[i].equals("-es2")) {
@@ -151,10 +151,10 @@ public class GPUUISceneNewtCanvasAWTDemo {
         window.setSize(width, height);
         window.setTitle("GraphUI Newt/AWT Demo: graph["+Region.getRenderModeString(rmode)+"], msaa "+SceneMSAASamples);
         window.setSurfaceScale(reqSurfacePixelScale);
-        final int[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new int[2]);
+        final float[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new float[2]);
 
         final GPUUISceneGLListener0A sceneGLListener = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(GraphAutoMode, DEBUG, TRACE) :
-                                                                     new GPUUISceneGLListener0A(rmode, DEBUG, TRACE);
+                                                                           new GPUUISceneGLListener0A(rmode, DEBUG, TRACE);
 
         window.addGLEventListener(sceneGLListener);
         sceneGLListener.attachInputListenerTo(window);
@@ -180,7 +180,7 @@ public class GPUUISceneNewtCanvasAWTDemo {
                frame.setVisible(true);
            }
         });
-        final int[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new int[2]);
+        final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]);
         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
index 16d56a0..29705d3 100644 (file)
@@ -20,7 +20,7 @@ public class GPUUISceneNewtDemo {
     static boolean GraphMSAAMode = false;
     static float GraphAutoMode = GPUUISceneGLListener0A.DefaultNoAADPIThreshold;
 
-    static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+    static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
 
     public static void main(final String[] args) {
         int width = 800, height = 400;
@@ -66,7 +66,7 @@ public class GPUUISceneNewtDemo {
                     y = MiscUtils.atoi(args[i], y);
                 } else if(args[i].equals("-pixelScale")) {
                     i++;
-                    final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+                    final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]);
                     reqSurfacePixelScale[0] = pS;
                     reqSurfacePixelScale[1] = pS;
                 } else if(args[i].equals("-es2")) {
@@ -126,7 +126,7 @@ public class GPUUISceneNewtDemo {
         window.setSize(width, height);
         window.setTitle("GraphUI Newt Demo: graph["+Region.getRenderModeString(rmode)+"], msaa "+SceneMSAASamples);
         window.setSurfaceScale(reqSurfacePixelScale);
-        final int[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new int[2]);
+        final float[] valReqSurfacePixelScale = window.getRequestedSurfaceScale(new float[2]);
 
         final GPUUISceneGLListener0A sceneGLListener = 0 < GraphAutoMode ? new GPUUISceneGLListener0A(GraphAutoMode, DEBUG, TRACE) :
                                                                      new GPUUISceneGLListener0A(rmode, DEBUG, TRACE);
@@ -145,7 +145,7 @@ public class GPUUISceneNewtDemo {
         });
 
         window.setVisible(true);
-        final int[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new int[2]);
+        final float[] hasSurfacePixelScale1 = window.getCurrentSurfaceScale(new float[2]);
         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
index b074297..032cf4f 100644 (file)
@@ -40,6 +40,8 @@ import java.awt.Dimension;
 import java.awt.Frame;
 import java.awt.Label;
 
+import jogamp.nativewindow.SurfaceScaleUtils;
+
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Before;
@@ -178,8 +180,8 @@ public class TestAWT03GLCanvasRecreate01 extends UITestCase {
     }
 
     private void assertSize(final Dimension expSize) {
-        final int[] scale = { 1, 1 };
-        glComp.getNativeSurfaceScale(scale);
+        final float[] scale = { 1f, 1f };
+        glComp.getMaximumSurfaceScale(scale);
 
         final Dimension hasSize = glComp.getSize(null);
 
@@ -188,8 +190,8 @@ public class TestAWT03GLCanvasRecreate01 extends UITestCase {
         Assert.assertTrue("AWT Size.height mismatch: expected "+expSize+", has "+hasSize,
                 Math.abs(expSize.height-hasSize.height) <= sizeEps);
 
-        final int expSurfWidth = expSize.width * scale[0];
-        final int expSurfHeight = expSize.height * scale[0];
+        final int expSurfWidth = SurfaceScaleUtils.scale(expSize.width, scale[0]);
+        final int expSurfHeight = SurfaceScaleUtils.scale(expSize.height, scale[0]);
         final int hasSurfWidth = glComp.getSurfaceWidth();
         final int hasSurfHeight = glComp.getSurfaceHeight();
 
index b2d4877..c4d9633 100644 (file)
@@ -41,6 +41,8 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
 import java.awt.BorderLayout;
 import java.awt.Dimension;
 
+import jogamp.nativewindow.SurfaceScaleUtils;
+
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Before;
@@ -179,8 +181,8 @@ public class TestAWT03GLJPanelRecreate01 extends UITestCase {
     }
 
     private void assertSize(final Dimension expSize) {
-        final int[] scale = { 1, 1 };
-        glComp.getNativeSurfaceScale(scale);
+        final float[] scale = { 1f, 1f };
+        glComp.getMaximumSurfaceScale(scale);
 
         final Dimension hasSize = glComp.getSize(null);
 
@@ -189,8 +191,8 @@ public class TestAWT03GLJPanelRecreate01 extends UITestCase {
         Assert.assertTrue("AWT Size.height mismatch: expected "+expSize+", has "+hasSize,
                 Math.abs(expSize.height-hasSize.height) <= sizeEps);
 
-        final int expSurfWidth = expSize.width * scale[0];
-        final int expSurfHeight = expSize.height * scale[0];
+        final int expSurfWidth = SurfaceScaleUtils.scale(expSize.width, scale[0]);
+        final int expSurfHeight = SurfaceScaleUtils.scale(expSize.height, scale[0]);
         final int hasSurfWidth = glComp.getSurfaceWidth();
         final int hasSurfHeight = glComp.getSurfaceHeight();
 
index d8c4341..6d682bb 100644 (file)
@@ -55,8 +55,6 @@ import java.awt.Dimension;
 import java.awt.EventQueue;
 import java.awt.Frame;
 import java.awt.TextArea;
-import java.awt.event.ComponentEvent;
-import java.awt.event.ComponentListener;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
@@ -80,7 +78,7 @@ public class TestGearsES2AWT extends UITestCase {
     static int xpos = 10, ypos = 10;
     static FrameLayout frameLayout = FrameLayout.None;
     static ResizeBy resizeBy = ResizeBy.Component;
-    static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+    static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
 
     static boolean forceES2 = false;
     static boolean forceGL3 = false;
@@ -171,7 +169,7 @@ public class TestGearsES2AWT extends UITestCase {
         Assert.assertNotNull(glCanvas);
         setSize(resizeBy, frame, false, glCanvas, new Dimension(width, height));
         glCanvas.setSurfaceScale(reqSurfacePixelScale);
-        final int[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new int[2]);
+        final float[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new float[2]);
         frame.setLocation(xpos, ypos);
 
         switch( frameLayout) {
@@ -215,29 +213,23 @@ public class TestGearsES2AWT extends UITestCase {
         }
         setTitle(frame, glCanvas, caps);
 
-        frame.addComponentListener(new ComponentListener() {
-            @Override
-            public void componentResized(final ComponentEvent e) {
-                setTitle(frame, glCanvas, caps);
-            }
-
-            @Override
-            public void componentMoved(final ComponentEvent e) {
-                setTitle(frame, glCanvas, caps);
-            }
-
-            @Override
-            public void componentShown(final ComponentEvent e) { }
-
-            @Override
-            public void componentHidden(final ComponentEvent e) { }
-        });
-
         final GearsES2 demo = new GearsES2(swapInterval);
         glCanvas.addGLEventListener(demo);
 
         final SnapshotGLEventListener snap = new SnapshotGLEventListener();
         glCanvas.addGLEventListener(snap);
+        glCanvas.addGLEventListener(new GLEventListener() {
+            @Override
+            public void init(final GLAutoDrawable drawable) { }
+            @Override
+            public void dispose(final GLAutoDrawable drawable) { }
+            @Override
+            public void display(final GLAutoDrawable drawable) { }
+            @Override
+            public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+                setTitle(frame, glCanvas, caps);
+            }
+        });
 
         final Animator animator = useAnimator ? new Animator(glCanvas) : null;
         if( useAnimator && exclusiveContext ) {
@@ -254,24 +246,22 @@ public class TestGearsES2AWT extends UITestCase {
                     return;
                 }
                 if(e.getKeyChar()=='x') {
-                    final int[] hadSurfacePixelScale = glCanvas.getCurrentSurfaceScale(new int[2]);
-                    final int[] reqSurfacePixelScale;
+                    final float[] hadSurfacePixelScale = glCanvas.getCurrentSurfaceScale(new float[2]);
+                    final float[] reqSurfacePixelScale;
                     if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
                     } else {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
                     }
                     System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
                     glCanvas.setSurfaceScale(reqSurfacePixelScale);
-                    final int[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new int[2]);
-                    final int[] hasSurfacePixelScale0 = glCanvas.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
-                    final int[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new int[2]);
+                    final float[] valReqSurfacePixelScale = glCanvas.getRequestedSurfaceScale(new float[2]);
+                    final float[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new float[2]);
                     System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
                                        reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                                        valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                                        hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
                     setTitle(frame, glCanvas, caps);
-                    Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
                 }
             } };
         new AWTKeyAdapter(kl, glCanvas).addTo(glCanvas);
@@ -288,13 +278,11 @@ public class TestGearsES2AWT extends UITestCase {
         Assert.assertEquals(true,  AWTRobotUtil.waitForVisible(frame, true));
         Assert.assertEquals(true,  AWTRobotUtil.waitForRealized(glCanvas, true));
 
-        final int[] hasSurfacePixelScale0 = glCanvas.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
-        final int[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new int[2]);
+        final float[] hasSurfacePixelScale1 = glCanvas.getCurrentSurfaceScale(new float[2]);
         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
         setTitle(frame, glCanvas, caps);
-        Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
 
         if( useAnimator ) {
             animator.start();
@@ -446,7 +434,7 @@ public class TestGearsES2AWT extends UITestCase {
                 rh = MiscUtils.atoi(args[i], rh);
             } else if(args[i].equals("-pixelScale")) {
                 i++;
-                final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+                final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]);
                 reqSurfacePixelScale[0] = pS;
                 reqSurfacePixelScale[1] = pS;
             } else if(args[i].equals("-layout")) {
index 340816a..0f2b891 100644 (file)
@@ -33,11 +33,8 @@ import java.awt.BorderLayout;
 import java.awt.Dimension;
 import java.awt.DisplayMode;
 import java.awt.GraphicsDevice;
-import java.awt.event.ComponentEvent;
-import java.awt.event.ComponentListener;
 import java.lang.reflect.InvocationTargetException;
 
-import javax.media.nativewindow.NativeSurface;
 import javax.media.nativewindow.ScalableSurface;
 import javax.media.nativewindow.util.Rectangle;
 import javax.media.nativewindow.util.RectangleImmutable;
@@ -50,8 +47,6 @@ import javax.media.opengl.awt.GLJPanel;
 import javax.swing.JFrame;
 import javax.swing.SwingUtilities;
 
-import jogamp.common.os.PlatformPropsImpl;
-
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Assume;
@@ -60,8 +55,13 @@ import org.junit.Test;
 import org.junit.FixMethodOrder;
 import org.junit.runners.MethodSorters;
 
-import com.jogamp.common.os.Platform;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Screen;
 import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.newt.event.MonitorModeListener;
 import com.jogamp.newt.event.TraceKeyAdapter;
 import com.jogamp.newt.event.TraceWindowAdapter;
 import com.jogamp.newt.event.awt.AWTKeyAdapter;
@@ -90,7 +90,7 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
     static boolean manualTest = false;
     static boolean skipGLOrientationVerticalFlip = false;
     static int xpos = 10, ypos = 10;
-    static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+    static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
 
     @BeforeClass
     public static void initClass() {
@@ -139,7 +139,7 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
         glJPanel.setPreferredSize(wsize);
         glJPanel.setSize(wsize);
         glJPanel.setSurfaceScale(reqSurfacePixelScale);
-        final int[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new int[2]);
+        final float[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new float[2]);
         if( caps.isBitmap() || caps.getGLProfile().isGL2() ) {
             final Gears gears = new Gears(swapInterval);
             gears.setFlipVerticalInGLOrientation(skipGLOrientationVerticalFlip);
@@ -162,29 +162,10 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
             public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
                 setTitle(frame, glJPanel, caps);
             }
-
         });
         setTitle(frame, glJPanel, caps);
         frame.setLocation(xpos, ypos);
 
-        frame.addComponentListener(new ComponentListener() {
-            @Override
-            public void componentResized(final ComponentEvent e) {
-                setTitle(frame, glJPanel, caps);
-            }
-
-            @Override
-            public void componentMoved(final ComponentEvent e) {
-                setTitle(frame, glJPanel, caps);
-            }
-
-            @Override
-            public void componentShown(final ComponentEvent e) { }
-
-            @Override
-            public void componentHidden(final ComponentEvent e) { }
-        });
-
         final FPSAnimator animator = useAnimator ? new FPSAnimator(glJPanel, 60) : null;
 
         SwingUtilities.invokeAndWait(new Runnable() {
@@ -197,13 +178,11 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
         Assert.assertEquals(true,  AWTRobotUtil.waitForVisible(frame, true));
         Assert.assertEquals(true,  AWTRobotUtil.waitForRealized(glJPanel, true));
 
-        final int[] hasSurfacePixelScale0 = glJPanel.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
-        final int[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new int[2]);
+        final float[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new float[2]);
         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
         setTitle(frame, glJPanel, caps);
-        Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
 
         if( useAnimator ) {
             animator.setUpdateFPSFrames(60, System.err);
@@ -231,31 +210,44 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
                     System.err.printf("GetPixelScale: NW Screen: %s%n", glJPanel.getNativeSurface().getGraphicsConfiguration().getScreen());
                     System.err.printf("GetPixelScale: Panel Bounds: %s window-units%n", r.toString());
                     System.err.printf("GetPixelScale: Panel Resolution: %d x %d pixel-units%n", glJPanel.getSurfaceWidth(), glJPanel.getSurfaceHeight());
-                    if( Platform.OSType.MACOS == PlatformPropsImpl.OS_TYPE ) {
-                        final int[] screenIndexOut = { 0 };
-                        final double pixelScale = jogamp.nativewindow.macosx.OSXUtil.GetPixelScale(r, screenIndexOut);
-                        System.err.printf("GetPixelScale: PixelScale %f on screen-idx %d%n", pixelScale, screenIndexOut[0]);
+                    {
+                        final Display dpy = NewtFactory.createDisplay(null);
+                        final Screen screen = NewtFactory.createScreen(dpy, 0);
+                        screen.addReference();
+                        final MonitorModeListener sml = new MonitorModeListener() {
+                            @Override
+                            public void monitorModeChangeNotify(final MonitorEvent me) {
+                            }
+                            @Override
+                            public void monitorModeChanged(final MonitorEvent me, final boolean success) {
+                            }
+                        };
+                        screen.addMonitorModeListener(sml);
+                        try {
+                            final MonitorDevice md = screen.getMainMonitor(r);
+                            System.err.printf("GetPixelScale: %s%n", md.toString());
+                        } finally {
+                            screen.removeReference();
+                        }
                     }
                     System.err.println();
                 } else if(e.getKeyChar()=='x') {
-                    final int[] hadSurfacePixelScale = glJPanel.getCurrentSurfaceScale(new int[2]);
-                    final int[] reqSurfacePixelScale;
+                    final float[] hadSurfacePixelScale = glJPanel.getCurrentSurfaceScale(new float[2]);
+                    final float[] reqSurfacePixelScale;
                     if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
                     } else {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
                     }
                     System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
                     glJPanel.setSurfaceScale(reqSurfacePixelScale);
-                    final int[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new int[2]);
-                    final int[] hasSurfacePixelScale0 = glJPanel.getNativeSurface().convertToPixelUnits(new int[] { 1, 1 });
-                    final int[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new int[2]);
+                    final float[] valReqSurfacePixelScale = glJPanel.getRequestedSurfaceScale(new float[2]);
+                    final float[] hasSurfacePixelScale1 = glJPanel.getCurrentSurfaceScale(new float[2]);
                     System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
                                        reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                                        valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                                        hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
                     setTitle(frame, glJPanel, caps);
-                    Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
                 } else if(e.getKeyChar()=='m') {
                     final GLCapabilitiesImmutable capsPre = glJPanel.getChosenGLCapabilities();
                     final GLCapabilities capsNew = new GLCapabilities(capsPre.getGLProfile());
@@ -520,7 +512,7 @@ public class TestGearsES2GLJPanelAWT extends UITestCase {
                 rh = MiscUtils.atoi(args[i], rh);
             } else if(args[i].equals("-pixelScale")) {
                 i++;
-                final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+                final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]);
                 reqSurfacePixelScale[0] = pS;
                 reqSurfacePixelScale[1] = pS;
             } else if(args[i].equals("-userVFlip")) {
index eb25366..3aa1519 100644 (file)
@@ -85,7 +85,7 @@ public class TestGearsES2NEWT extends UITestCase {
     static int screenIdx = 0;
     static PointImmutable wpos;
     static DimensionImmutable wsize, rwsize=null;
-    static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+    static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
 
     static long duration = 500; // ms
     static boolean opaque = true;
@@ -137,7 +137,7 @@ public class TestGearsES2NEWT extends UITestCase {
         final GLWindow glWindow = GLWindow.create(screen, caps);
         Assert.assertNotNull(glWindow);
         glWindow.setSurfaceScale(reqSurfacePixelScale);
-        final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
+        final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
         glWindow.setSize(wsize.getWidth(), wsize.getHeight());
         if(null != wpos) {
             glWindow.setPosition(wpos.getX(), wpos.getY());
@@ -392,24 +392,22 @@ public class TestGearsES2NEWT extends UITestCase {
                             glWindow.setExclusiveContextThread(t);
                     } }.start();
                 } else if(e.getKeyChar()=='x') {
-                    final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]);
-                    final int[] reqSurfacePixelScale;
+                    final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]);
+                    final float[] reqSurfacePixelScale;
                     if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
                     } else {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
                     }
                     System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
                     glWindow.setSurfaceScale(reqSurfacePixelScale);
-                    final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
-                    final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 });
-                    final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+                    final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
+                    final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]);
                     System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
-                                       reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
-                                       valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
-                                       hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+                            reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
                     setTitle(glWindow, caps);
-                    Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
                 }
             }
         });
@@ -482,13 +480,11 @@ public class TestGearsES2NEWT extends UITestCase {
         System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
         System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
 
-        final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 });
-        final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+        final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]);
         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
         setTitle(glWindow, caps);
-        Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
 
         snap.setMakeSnapshot();
 
@@ -669,7 +665,7 @@ public class TestGearsES2NEWT extends UITestCase {
                 usePos = true;
             } else if(args[i].equals("-pixelScale")) {
                 i++;
-                final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+                final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]);
                 reqSurfacePixelScale[0] = pS;
                 reqSurfacePixelScale[1] = pS;
             } else if(args[i].equals("-rwidth")) {
index 2dca3ad..7af6fd1 100644 (file)
@@ -86,7 +86,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase {
     static DimensionImmutable wsize, rwsize = null;
     static FrameLayout frameLayout = FrameLayout.None;
     static ResizeBy resizeBy = ResizeBy.Component;
-    static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+    static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
 
     static long duration = 500; // ms
     static boolean opaque = true;
@@ -195,7 +195,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase {
         final GLWindow glWindow = GLWindow.create(screen, caps);
         Assert.assertNotNull(glWindow);
         glWindow.setSurfaceScale(reqSurfacePixelScale);
-        final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
+        final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
 
         final NewtCanvasAWT newtCanvasAWT = new NewtCanvasAWT(glWindow);
         if ( shallUseOffscreenFBOLayer ) {
@@ -309,24 +309,22 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase {
                     return;
                 }
                 if(e.getKeyChar()=='x') {
-                    final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]);
-                    final int[] reqSurfacePixelScale;
+                    final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]);
+                    final float[] reqSurfacePixelScale;
                     if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
                     } else {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
                     }
                     System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
                     glWindow.setSurfaceScale(reqSurfacePixelScale);
-                    final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
-                    final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 });
-                    final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+                    final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
+                    final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]);
                     System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
                                        reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                                        valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                                        hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
                     setTitle(frame, newtCanvasAWT, glWindow, caps);
-                    Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
                 }
             } } );
 
@@ -359,13 +357,11 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase {
         System.err.println("GL chosen: "+glWindow.getChosenCapabilities());
         System.err.println("window pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
 
-        final int[] hasSurfacePixelScale0 = glWindow.convertToPixelUnits(new int[] { 1, 1 });
-        final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+        final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]);
         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
         setTitle(frame, newtCanvasAWT, glWindow, caps);
-        Assert.assertArrayEquals(hasSurfacePixelScale0, hasSurfacePixelScale1);
 
         if( null != rwsize ) {
             Thread.sleep(500); // 500ms delay
@@ -503,7 +499,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase {
                 usePos = true;
             } else if(args[i].equals("-pixelScale")) {
                 i++;
-                final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+                final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]);
                 reqSurfacePixelScale[0] = pS;
                 reqSurfacePixelScale[1] = pS;
             } else if(args[i].equals("-screen")) {
index e20bbef..db3f817 100644 (file)
@@ -63,7 +63,7 @@ import org.junit.runners.MethodSorters;
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class TestRulerNEWT01 extends UITestCase {
     static long durationPerTest = 500; // ms
-    static int[] reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+    static float[] reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
     static boolean manualTest = false;
 
     private void setTitle(final Window win) {
@@ -77,7 +77,7 @@ public class TestRulerNEWT01 extends UITestCase {
         final GLWindow glWindow = GLWindow.create(new GLCapabilities(GLProfile.getGL2ES2()));
         Assert.assertNotNull(glWindow);
         glWindow.setSurfaceScale(reqSurfacePixelScale);
-        final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
+        final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
         glWindow.setSize(640, 480);
 
         glWindow.addGLEventListener(new GLEventListener() {
@@ -183,19 +183,19 @@ public class TestRulerNEWT01 extends UITestCase {
                     return;
                 }
                 if(e.getKeyChar()=='x') {
-                    final int[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]);
-                    final int[] reqSurfacePixelScale;
+                    final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]);
+                    final float[] reqSurfacePixelScale;
                     if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
                     } else {
-                        reqSurfacePixelScale = new int[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+                        reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
                     }
                     System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
                     snap.setMakeSnapshot();
                     glWindow.setSurfaceScale(reqSurfacePixelScale);
-                    final int[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new int[2]);
-                    final int[] hasSurfacePixelScale = glWindow.getCurrentSurfaceScale(new int[2]);
-                    final int[] nativeSurfacePixelScale = glWindow.getNativeSurfaceScale(new int[2]);
+                    final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
+                    final float[] hasSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]);
+                    final float[] nativeSurfacePixelScale = glWindow.getMaximumSurfaceScale(new float[2]);
                     System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
                                        reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                                        valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
@@ -208,7 +208,7 @@ public class TestRulerNEWT01 extends UITestCase {
 
         glWindow.setVisible(true);
 
-        final int[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new int[2]);
+        final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]);
         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
@@ -243,7 +243,7 @@ public class TestRulerNEWT01 extends UITestCase {
                 durationPerTest = MiscUtils.atoi(args[++i], (int)durationPerTest);
             } else if(args[i].equals("-pixelScale")) {
                 i++;
-                final int pS = MiscUtils.atoi(args[i], reqSurfacePixelScale[0]);
+                final float pS = MiscUtils.atof(args[i], reqSurfacePixelScale[0]);
                 reqSurfacePixelScale[0] = pS;
                 reqSurfacePixelScale[1] = pS;
             } else if(args[i].equals("-manual")) {
index 8605606..059b890 100644 (file)
@@ -112,12 +112,12 @@ public class TestScreenMode00aNEWT extends UITestCase {
         final Rectangle viewport = new Rectangle(0, 0, 1920, 1080);
         final ArrayHashSet<MonitorMode> supportedModes = new ArrayHashSet<MonitorMode>();
         supportedModes.add(modeOut);
-        final MonitorDevice monOut = new MonitorDeviceImpl(null, -1, sizeMM, viewport, viewport, modeOut, supportedModes);
+        final MonitorDevice monOut = new MonitorDeviceImpl(null, -1, 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(null, cache, null, props, 0);
+            final MonitorDevice monIn = MonitorModeProps.streamInMonitorDevice(cache, null, null, props, 0, null);
             System.err.println("01 in : "+monIn);
 
             Assert.assertEquals(monOut.getCurrentMode(), monOut.getOriginalMode());
http://JogAmp.org git info: FAQ, tutorial and man pages.