diff options
author | Sven Gothel <[email protected]> | 2014-05-26 18:54:27 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-05-26 18:54:27 +0200 |
commit | 56d60b36798fa8dae48bf2aa5e2de6f3178ab0d1 (patch) | |
tree | 4c86190128414205d0b768780e3272e32bd1e81a /src/newt/classes/com | |
parent | 98ed02cdb7b325d8afde596a5ef04f97be2018d4 (diff) |
Bug 741 HiDPI: Refine Monitor/Screen [virtual] Viewport Definition / Add NEWT Support / Fix JAWT getPixelScale deadlock
- NativeWindow/Surface/NEWT API DOC: Define Coordinate System of Window and Screen
- OSXUtil: Add getPixelScale(..) via Screen index and 'windowOrView'
- JAWTWindow/JAWTUtil.getPixelScale(..): Use pre-fetched AWT GraphicsConfiguration to solve AWT-TreeLock (deadlock)
- [Virtual] Viewport of MonitorDevice and Screen:
- Properly calculate and expose [virtual] viewport in window and pixel units
- OSX Monitor viewports in pixel units are 'reconstructed'
- Window/Viewport to Monitor selection shall be perfomed via window units (unique)
- OSX NEWT Window create/init (native): Use given size and coordinates even in fullscreen mode
Don't override by quering NSScreen coordinates, trust given values.
- Fix test cases, i.e. usage of pixel- and window-units
Diffstat (limited to 'src/newt/classes/com')
-rw-r--r-- | src/newt/classes/com/jogamp/newt/MonitorDevice.java | 97 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/Screen.java | 52 | ||||
-rw-r--r-- | src/newt/classes/com/jogamp/newt/Window.java | 23 |
3 files changed, 112 insertions, 60 deletions
diff --git a/src/newt/classes/com/jogamp/newt/MonitorDevice.java b/src/newt/classes/com/jogamp/newt/MonitorDevice.java index af0ce0146..8e5d305dd 100644 --- a/src/newt/classes/com/jogamp/newt/MonitorDevice.java +++ b/src/newt/classes/com/jogamp/newt/MonitorDevice.java @@ -52,6 +52,9 @@ import com.jogamp.common.util.ArrayHashSet; * <li>{@link RectangleImmutable} viewport (rotated)</li> * </ul></li> * </ul> + * <p> + * All values of this interface are represented in pixel units, if not stated otherwise. + * </p> */ public abstract class MonitorDevice { protected final Screen screen; // backref @@ -61,16 +64,18 @@ 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 viewport; + protected Rectangle viewportPU; // in pixel units + protected Rectangle viewportWU; // in window units - protected MonitorDevice(Screen screen, int nativeId, DimensionImmutable sizeMM, Rectangle viewport, MonitorMode currentMode, ArrayHashSet<MonitorMode> supportedModes) { + protected MonitorDevice(Screen screen, int nativeId, DimensionImmutable sizeMM, Rectangle viewportPU, Rectangle viewportWU, MonitorMode currentMode, ArrayHashSet<MonitorMode> supportedModes) { this.screen = screen; this.nativeId = nativeId; this.sizeMM = sizeMM; this.originalMode = currentMode; this.supportedModes = supportedModes; this.currentMode = currentMode; - this.viewport = viewport; + this.viewportPU = viewportPU; + this.viewportWU = viewportWU; this.modeChanged = false; } @@ -170,11 +175,22 @@ public abstract class MonitorDevice { /** * Returns the {@link RectangleImmutable rectangular} portion - * of the rotated virtual {@link Screen} size in pixel units - * represented by this monitor. + * 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 */ public final RectangleImmutable getViewport() { - return viewport; + return viewportPU; + } + + /** + * Returns the {@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 + */ + public final RectangleImmutable getViewportInWindowUnits() { + return viewportWU; } /** @@ -184,46 +200,45 @@ public abstract class MonitorDevice { * @param y y-coord in pixel units */ public final boolean contains(final int x, final int y) { - return x >= viewport.getX() && - x < viewport.getX() + viewport.getWidth() && - y >= viewport.getY() && - y < viewport.getY() + viewport.getHeight() ; + return x >= viewportPU.getX() && + x < viewportPU.getX() + viewportPU.getWidth() && + y >= viewportPU.getY() && + y < viewportPU.getY() + viewportPU.getHeight() ; } /** - * Returns the coverage of given rectangle in pixel units - * w/ this {@link #getViewport() viewport}, i.e. between <code>0.0</code> and <code>1.0</code>. - * <p> - * Coverage is computed by: - * <pre> - * isect = viewport.intersection(r); - * coverage = area( isect ) / area( viewport ) ; - * </pre> - * </p> - * @param r {@link RectangleImmutable rectangle} in pixel units - */ - public final float coverage(final RectangleImmutable r) { - return viewport.coverage(r); - } - - /** - * Returns the union of the given monitor's {@link #getViewport() viewport} in pixel units. - * @param result storage for result, will be returned + * Calculates the union of the given monitor's {@link #getViewport() viewport} in pixel- and window units. + * @param viewport storage for result in pixel units, maybe null + * @param viewportInWindowUnits storage for result in window units, maybe null * @param monitors given list of monitors - * @return viewport representing the union of given monitor's viewport in pixel units, i.e. result storage for chaining */ - public static Rectangle unionOfViewports(final Rectangle result, final List<MonitorDevice> monitors) { - int x1=Integer.MAX_VALUE, y1=Integer.MAX_VALUE; - int x2=Integer.MIN_VALUE, y2=Integer.MIN_VALUE; + public static void unionOfViewports(final Rectangle viewport, final Rectangle viewportInWindowUnits, final List<MonitorDevice> monitors) { + int x1PU=Integer.MAX_VALUE, y1PU=Integer.MAX_VALUE; + int x2PU=Integer.MIN_VALUE, y2PU=Integer.MIN_VALUE; + int x1WU=Integer.MAX_VALUE, y1WU=Integer.MAX_VALUE; + int x2WU=Integer.MIN_VALUE, y2WU=Integer.MIN_VALUE; for(int i=monitors.size()-1; i>=0; i--) { - final RectangleImmutable vp = monitors.get(i).getViewport(); - x1 = Math.min(x1, vp.getX()); - x2 = Math.max(x2, vp.getX() + vp.getWidth()); - y1 = Math.min(y1, vp.getY()); - y2 = Math.max(y2, vp.getY() + vp.getHeight()); + if( null != viewport ) { + final RectangleImmutable viewPU = monitors.get(i).getViewport(); + x1PU = Math.min(x1PU, viewPU.getX()); + x2PU = Math.max(x2PU, viewPU.getX() + viewPU.getWidth()); + y1PU = Math.min(y1PU, viewPU.getY()); + y2PU = Math.max(y2PU, viewPU.getY() + viewPU.getHeight()); + } + if( null != viewportInWindowUnits ) { + final RectangleImmutable viewWU = monitors.get(i).getViewportInWindowUnits(); + x1WU = Math.min(x1WU, viewWU.getX()); + x2WU = Math.max(x2WU, viewWU.getX() + viewWU.getWidth()); + y1WU = Math.min(y1WU, viewWU.getY()); + y2WU = Math.max(y2WU, viewWU.getY() + viewWU.getHeight()); + } + } + if( null != viewport ) { + viewport.set(x1PU, y1PU, x2PU - x1PU, y2PU - y1PU); + } + if( null != viewportInWindowUnits ) { + viewportInWindowUnits.set(x1WU, y1WU, x2WU - x1WU, y2WU - y1WU); } - result.set(x1, y1, x2 - x1, y2 - y1); - return result; } public final boolean isOriginalMode() { @@ -247,6 +262,7 @@ public abstract class MonitorDevice { * <p> * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}. * </p> + * @see #queryCurrentMode() */ public final MonitorMode getCurrentMode() { return currentMode; @@ -257,6 +273,7 @@ public abstract class MonitorDevice { * <p> * The returned {@link MonitorMode} is element of the lists {@link #getSupportedModes()} and {@link Screen#getMonitorModes()}. * </p> + * @see #getCurrentMode() */ public abstract MonitorMode queryCurrentMode(); @@ -269,7 +286,7 @@ public abstract class MonitorDevice { @Override public String toString() { - return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, viewport "+viewport+ ", orig "+originalMode+", curr "+currentMode+ + return "Monitor[Id "+Display.toHexString(nativeId)+", "+sizeMM+" mm, viewport "+viewportPU+ " [pixels], "+viewportWU+" [window], orig "+originalMode+", curr "+currentMode+ ", modeChanged "+modeChanged+", modeCount "+supportedModes.size()+"]"; } } diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java index 919b98b45..cef254634 100644 --- a/src/newt/classes/com/jogamp/newt/Screen.java +++ b/src/newt/classes/com/jogamp/newt/Screen.java @@ -28,12 +28,14 @@ package com.jogamp.newt; import com.jogamp.newt.event.MonitorModeListener; + import jogamp.newt.Debug; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.List; + import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.util.Rectangle; @@ -41,7 +43,18 @@ import javax.media.nativewindow.util.RectangleImmutable; /** * A screen may span multiple {@link MonitorDevice}s representing their combined virtual size. - */ + * <p> + * All values of this interface are represented in pixel units, if not stated otherwise. + * </p> + * + * <a name="coordinateSystem"><h5>Coordinate System</h5></a> + * <p> + * <ul> + * <li>Screen space has it's origin in the top-left corner, and may not be at 0/0.</li> + * <li>{@link #getViewport() Virtual viewport} covers all {@link MonitorDevice}s {@link MonitorDevice#getViewport() viewports} and has it's origin in the top-left corner, and may not be at 0/0.</li> + * </ul> + * </p> +*/ public abstract class Screen { /** @@ -131,11 +144,15 @@ public abstract class Screen { public abstract int getIndex(); /** + * See <a href="#coordinateSystem"> Coordinate System</a>. + * * @return the x position of the virtual viewport's top-left origin in pixel units. */ public abstract int getX(); /** + * See <a href="#coordinateSystem"> Coordinate System</a>. + * * @return the y position of the virtual viewport's top-left origin in pixel units. */ public abstract int getY(); @@ -151,20 +168,20 @@ public abstract class Screen { public abstract int getHeight(); /** - * @return the <b>rotated</b> virtual viewport, i.e. origin and size in pixel units. - * @see #getViewportInWindowUnits(Window) + * See <a href="#coordinateSystem"> Coordinate System</a>. + * + * @return the <b>rotated</b> virtual viewport, i.e. top-left origin and size, in pixel units. + * @see #getViewportInWindowUnits() */ public abstract RectangleImmutable getViewport(); /** - * Returns a newly created {@link Rectangle} containing the <b>rotated</b> virtual viewport - * in window units of the given {@link Window} instance. - * @return rotated viewport values, i.e. origin and size, in pixel units. + * See <a href="#coordinateSystem"> Coordinate System</a>. + * + * @return the <b>rotated</b> virtual viewport, i.e. top-left origin and size, in window units. * @see #getViewport() */ - public final Rectangle getViewportInWindowUnits(final Window win) { - return win.convertToWindowUnits( (Rectangle) getViewport().cloneMutable() ); - } + public abstract RectangleImmutable getViewportInWindowUnits(); /** * @return the associated Display @@ -192,12 +209,12 @@ public abstract class Screen { public abstract List<MonitorDevice> getMonitorDevices(); /** - * Returns the {@link MonitorDevice} with the highest {@link MonitorDevice#getViewport() viewport} - * {@link MonitorDevice#coverage(RectangleImmutable) coverage} of the given rectangle in pixel units. + * Returns the {@link MonitorDevice} with the highest {@link MonitorDevice#getViewportInWindowUnits() viewport} + * {@link RectangleImmutable#coverage(RectangleImmutable) coverage} of the given rectangle in window units. * <p> * If no coverage is detected the first {@link MonitorDevice} is returned. * </p> - * @param r arbitrary rectangle in pixel units + * @param r arbitrary rectangle in window units */ public final MonitorDevice getMainMonitor(final RectangleImmutable r) { MonitorDevice res = null; @@ -205,7 +222,7 @@ public abstract class Screen { final List<MonitorDevice> monitors = getMonitorDevices(); for(int i=monitors.size()-1; i>=0; i--) { final MonitorDevice monitor = monitors.get(i); - final float coverage = monitor.coverage(r); + final float coverage = monitor.getViewportInWindowUnits().coverage(r); if( coverage > maxCoverage ) { maxCoverage = coverage; res = monitor; @@ -218,15 +235,16 @@ public abstract class Screen { } /** - * Returns the union of all monitor's {@link MonitorDevice#getViewport() viewport} in pixel units. + * Calculates the union of all monitor's {@link MonitorDevice#getViewport() viewport} in pixel- and window units. * <p> * Should be equal to {@link #getX()}, {@link #getY()}, {@link #getWidth()} and {@link #getHeight()}, * however, some native toolkits may choose a different virtual screen area. * </p> - * @param result storage for result, will be returned + * @param viewport storage for result in pixel units, maybe null + * @param viewportInWindowUnits storage for result in window units, maybe null */ - public final Rectangle unionOfMonitorViewportSize(final Rectangle result) { - return MonitorDevice.unionOfViewports(result, getMonitorDevices()); + public final void unionOfMonitorViewports(final Rectangle viewport, final Rectangle viewportInWindowUnits) { + MonitorDevice.unionOfViewports(viewport, viewportInWindowUnits, getMonitorDevices()); } /** diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 872d67087..57fcb626d 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -46,7 +46,6 @@ import javax.media.nativewindow.CapabilitiesChooser; import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.WindowClosingProtocol; -import javax.media.nativewindow.util.Point; import javax.media.nativewindow.util.Rectangle; import javax.media.nativewindow.util.RectangleImmutable; @@ -65,6 +64,20 @@ import javax.media.nativewindow.util.RectangleImmutable; * window operation to an instance of this interface while providing OpenGL * functionality. * </p> + * <p> + * All values of this interface are represented in window units, if not stated otherwise. + * </p> + * + * <a name="coordinateSystem"><h5>Coordinate System</h5></a> + * <p> + * <ul> + * <li>Screen space has it's origin in the top-left corner, and may not be at 0/0.</li> + * <li>Window origin is in it's top-left corner, see {@link #getX()} and {@link #getY()}. </li> + * <li>Window client-area excludes {@link #getInsets() insets}, i.e. window decoration.</li> + * <li>Window origin is relative to it's parent window if exist, or the screen position (top-level).</li> + * </ul> + * See {@link NativeWindow} and {@link Screen}. + * </p> * <a name="customwindowicons"><h5>Custom Window Icons</h5></a> * <p> * Custom window icons can be defined via system property <code>newt.window.icons</code>, @@ -108,8 +121,8 @@ public interface Window extends NativeWindow, WindowClosingProtocol { Screen getScreen(); /** - * Returns the {@link MonitorDevice} which {@link MonitorDevice#getViewport() viewport} - * {@link MonitorDevice#coverage(RectangleImmutable) covers} this window the most. + * Returns the {@link MonitorDevice} with the highest {@link MonitorDevice#getViewportInWindowUnits() viewport} + * {@link RectangleImmutable#coverage(RectangleImmutable) coverage} of this window. * <p> * If no coverage is detected the first {@link MonitorDevice} is returned. * </p> @@ -242,6 +255,10 @@ public interface Window extends NativeWindow, WindowClosingProtocol { /** * Returns a newly created {@link Rectangle} containing the scaled window origin, {@link #getX()} & {@link #getY()}, * and size, {@link #getSurfaceWidth()} & {@link #getSurfaceHeight()}, in pixel units. + * + * @deprecated The returned position in pixel units might be erroneous in case of multiple monitor setup where a mixed pixel-scale exist, + * since this method currently does not take the monitor viewport and each of it's pixel-scale into account (expensive). + * Either we fix this issue or remove this method at a later time. */ Rectangle getSurfaceBounds(); |