--- old/modules/graphics/src/main/java/javafx/stage/Screen.java 2016-03-30 23:38:06.000000000 -0700 +++ new/modules/graphics/src/main/java/javafx/stage/Screen.java 2016-03-30 23:38:05.000000000 -0700 @@ -32,7 +32,6 @@ import javafx.collections.ObservableList; import javafx.geometry.Rectangle2D; -import com.sun.javafx.stage.ScreenHelper; import com.sun.javafx.tk.ScreenConfigurationAccessor; import com.sun.javafx.tk.Toolkit; @@ -72,10 +71,6 @@ FXCollections.unmodifiableObservableList(screens); static { - ScreenHelper.setScreenAccessor(new ScreenHelper.ScreenAccessor() { - @Override public float getRenderScale(Screen screen) { return screen.getRenderScale(); } - }); - accessor = Toolkit.getToolkit().setScreenConfigurationListener(() -> updateConfiguration()); } @@ -138,7 +133,8 @@ int visualWidth = accessor.getVisualWidth(obj); int visualHeight = accessor.getVisualHeight(obj); double dpi = accessor.getDPI(obj); - float renderScale = accessor.getRenderScale(obj); + float outScaleX = accessor.getRecommendedOutputScaleX(obj); + float outScaleY = accessor.getRecommendedOutputScaleY(obj); if ((screen == null) || (screen.bounds.getMinX() != minX) || (screen.bounds.getMinY() != minY) || @@ -149,13 +145,15 @@ (screen.visualBounds.getWidth() != visualWidth) || (screen.visualBounds.getHeight() != visualHeight) || (screen.dpi != dpi) || - (screen.renderScale != renderScale)) + (screen.outputScaleX != outScaleX) || + (screen.outputScaleY != outScaleY)) { Screen s = new Screen(); s.bounds = new Rectangle2D(minX, minY, width, height); s.visualBounds = new Rectangle2D(visualMinX, visualMinY, visualWidth, visualHeight); s.dpi = dpi; - s.renderScale = renderScale; + s.outputScaleX = outScaleX; + s.outputScaleY = outScaleY; return s; } else { return null; @@ -239,6 +237,10 @@ private Rectangle2D bounds = Rectangle2D.EMPTY; /** * Gets the bounds of this {@code Screen}. + * The bounds will be reported adjusted for the {@code outputScale} so + * that resizing a {@code Window} with these bounds and the same + * {@code outputScale} as this {@code Screen} will cover the entire + * screen. * @return The bounds of this {@code Screen} */ public final Rectangle2D getBounds() { @@ -276,17 +278,39 @@ } /** - * The scale factor of this {@code Screen}. + * The recommended output scale factor of this {@code Screen} in the + * X direction. + */ + private float outputScaleX; + + /** + * Gets the recommended output scale factor of this {@code Screen} in + * the horizontal ({@code X}) direction. + * This scale factor should be applied to a scene in order to compensate + * for the resolution and viewing distance of the output device. + * The visual bounds will be reported relative to this scale factor. + * @return the recommended output scale factor for the screen. + */ + public final double getOutputScaleX() { + return outputScaleX; + } + + /** + * The recommended output scale factor of this {@code Screen} in the + * Y direction. */ - private float renderScale; + private float outputScaleY; /** - * Gets the scale factor of this {@code Screen}. - * E.g. on Retina displays on Mac the scale factor may be equal to 2.0. - * On regular displays this method returns 1.0. + * Gets the recommended output scale factor of this {@code Screen} in + * the vertical ({@code Y}) direction. + * This scale factor will be applied to the scene in order to compensate + * for the resolution and viewing distance of the output device. + * The visual bounds will be reported relative to this scale factor. + * @return the recommended output scale factor for the screen. */ - private float getRenderScale() { - return renderScale; + public final double getOutputScaleY() { + return outputScaleY; } /** @@ -298,7 +322,8 @@ bits = 37L * bits + bounds.hashCode(); bits = 37L * bits + visualBounds.hashCode(); bits = 37L * bits + Double.doubleToLongBits(dpi); - bits = 37L * bits + Float.floatToIntBits(renderScale); + bits = 37L * bits + Float.floatToIntBits(outputScaleX); + bits = 37L * bits + Float.floatToIntBits(outputScaleY); return (int) (bits ^ (bits >> 32)); } @@ -314,7 +339,7 @@ return (bounds == null ? other.bounds == null : bounds.equals(other.bounds)) && (visualBounds == null ? other.visualBounds == null : visualBounds.equals(other.visualBounds)) && other.dpi == dpi - && other.renderScale == renderScale; + && other.outputScaleX == outputScaleX && other.outputScaleY == outputScaleY; } else return false; } @@ -323,6 +348,7 @@ * @return a string representation of this {@code Screen} object. */ @Override public String toString() { - return super.toString() + " bounds:" + bounds + " visualBounds:" + visualBounds + " dpi:" + dpi + " renderScale:" + renderScale; + return super.toString() + " bounds:" + bounds + " visualBounds:" + visualBounds + " dpi:" + + dpi + " outputScale:(" + outputScaleX + "," + outputScaleY + ")"; } } --- old/modules/graphics/src/main/java/javafx/stage/Window.java 2016-03-30 23:38:07.000000000 -0700 +++ new/modules/graphics/src/main/java/javafx/stage/Window.java 2016-03-30 23:38:07.000000000 -0700 @@ -28,10 +28,7 @@ import java.security.AllPermission; import java.security.AccessControlContext; import java.security.AccessController; -import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import com.sun.javafx.collections.annotations.ReturnsUnmodifiableCollection; import javafx.beans.property.DoubleProperty; @@ -45,6 +42,7 @@ import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.ReadOnlyDoubleWrapper; import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleDoubleProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; @@ -58,7 +56,6 @@ import javafx.scene.Scene; import com.sun.javafx.util.Utils; -import com.sun.javafx.util.WeakReferenceQueue; import com.sun.javafx.css.StyleManager; import com.sun.javafx.stage.WindowEventDispatcher; import com.sun.javafx.stage.WindowHelper; @@ -67,6 +64,8 @@ import com.sun.javafx.tk.TKScene; import com.sun.javafx.tk.TKStage; import com.sun.javafx.tk.Toolkit; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; /** @@ -108,6 +107,13 @@ } @Override + public void notifyScaleChanged(Window window, + double newOutputScaleX, + double newOutputScaleY) { + window.updateOutputScales(newOutputScaleX, newOutputScaleY); + } + + @Override public void notifyScreenChanged(Window window, Object from, Object to) { @@ -115,15 +121,15 @@ } @Override - public float getUIScale(Window window) { + public float getPlatformScaleX(Window window) { TKStage peer = window.impl_peer; - return peer == null ? 1.0f : peer.getUIScale(); + return peer == null ? 1.0f : peer.getPlatformScaleX(); } @Override - public float getRenderScale(Window window) { + public float getPlatformScaleY(Window window) { TKStage peer = window.impl_peer; - return peer == null ? 1.0f : peer.getRenderScale(); + return peer == null ? 1.0f : peer.getPlatformScaleY(); } @Override @@ -289,6 +295,153 @@ } } + private void updateOutputScales(double sx, double sy) { + // We call updateRenderScales() before updating the property + // values so that an application can listen to the properties + // and set their own values overriding the default values we set. + updateRenderScales(sx, sy); + // Now set the properties and trigger any potential listeners. + outputScaleX.set(sx); + outputScaleY.set(sy); + } + + void updateRenderScales(double sx, double sy) { + boolean forceInt = forceIntegerRenderScale.get(); + if (!renderScaleX.isBound()) { + renderScaleX.set(forceInt ? Math.ceil(sx) : sx); + } + if (!renderScaleY.isBound()) { + renderScaleY.set(forceInt ? Math.ceil(sy) : sy); + } + } + + /** + * The scale that the {@code Window} will apply to horizontal scene + * coordinates in all stages of rendering and compositing the output + * to the screen or other destination device. + * This property is updated asynchronously by the system at various + * times including: + * + * @see outputScaleThreshold + */ + private ReadOnlyDoubleWrapper outputScaleX = + new ReadOnlyDoubleWrapper(this, "outputScaleX", 1.0); + public final double getOutputScaleX() { + return outputScaleX.get(); + } + public final ReadOnlyDoubleProperty outputScaleXProperty() { + return outputScaleX.getReadOnlyProperty(); + } + + /** + * The scale that the {@code Window} will apply to vertical scene + * coordinates in all stages of rendering and compositing the output + * to the screen or other destination device. + * This property is updated asynchronously by the system at various + * times including: + * + * @see outputScaleThreshold + */ + private ReadOnlyDoubleWrapper outputScaleY = + new ReadOnlyDoubleWrapper(this, "outputScaleY", 1.0); + public final double getOutputScaleY() { + return outputScaleY.get(); + } + public final ReadOnlyDoubleProperty outputScaleYProperty() { + return outputScaleY.getReadOnlyProperty(); + } + + /** + * Boolean property that controls whether only integer render scales + * are set by default by the system when there is a change in the + * associated output scale. + * The {@code renderScale} properties will be updated directly and + * simultaneously with any changes in the associated {@code outputScale} + * properties, but the values can be overridden by subsequent calls to + * the {@code setRenderScale} setters or through appropriate use of + * binding. + * This property will not prevent setting non-integer scales + * directly using the {@code renderScale} property object or the + * convenience setter method. + */ + private BooleanProperty forceIntegerRenderScale = + new SimpleBooleanProperty(this, "forceIntegerRenderScale", false) { + @Override + protected void invalidated() { + updateRenderScales(getOutputScaleX(), + getOutputScaleY()); + } + }; + public final void setForceIntegerRenderScale(boolean forced) { + forceIntegerRenderScale.set(forced); + } + public final boolean isForceIntegerRenderScale() { + return forceIntegerRenderScale.get(); + } + public final BooleanProperty forceIntegerRenderScaleProperty() { + return forceIntegerRenderScale; + } + + /** + * The horizontal scale that the {@code Window} will use when rendering + * its {@code Scene} to the rendering buffer. + * This property is automatically updated whenever there is a change in + * the {@link outputScaleX} property and can be overridden either by + * calling {@code setRenderScaleX()} in response to a listener on the + * {@code outputScaleX} property or by binding it appropriately. + */ + private DoubleProperty renderScaleX = + new SimpleDoubleProperty(this, "renderScaleX", 1.0) { + @Override + protected void invalidated() { + peerBoundsConfigurator.setRenderScaleX(get()); + } + }; + public final void setRenderScaleX(double scale) { + renderScaleX.set(scale); + } + public final double getRenderScaleX() { + return renderScaleX.get(); + } + public final DoubleProperty renderScaleXProperty() { + return renderScaleX; + } + + /** + * The vertical scale that the {@code Window} will use when rendering + * its {@code Scene} to the rendering buffer. + * This property is automatically updated whenever there is a change in + * the {@link outputScaleY} property and can be overridden either by + * calling {@code setRenderScaleY()} in response to a listener on the + * {@code outputScaleY} property or by binding it appropriately. + */ + private DoubleProperty renderScaleY = + new SimpleDoubleProperty(this, "renderScaleY", 1.0) { + @Override + protected void invalidated() { + peerBoundsConfigurator.setRenderScaleY(get()); + } + }; + public final void setRenderScaleY(double scale) { + renderScaleY.set(scale); + } + public final double getRenderScaleY() { + return renderScaleY.get(); + } + public final DoubleProperty renderScaleYProperty() { + return renderScaleY; + } + private boolean xExplicit = false; /** * The horizontal location of this {@code Stage} on the screen. Changing @@ -842,6 +995,7 @@ // Setup listener for changes coming back from peer impl_peer.setTKStageListener(peerListener); + updateOutputScales(impl_peer.getOutputScaleX(), impl_peer.getOutputScaleY()); // Register pulse listener tk.addStageTkPulseListener(peerBoundsConfigurator); @@ -1205,6 +1359,8 @@ * the next pulse. */ private final class TKBoundsConfigurator implements TKPulseListener { + private double renderScaleX; + private double renderScaleY; private double x; private double y; private float xGravity; @@ -1220,6 +1376,16 @@ reset(); } + public void setRenderScaleX(final double renderScaleX) { + this.renderScaleX = renderScaleX; + setDirty(); + } + + public void setRenderScaleY(final double renderScaleY) { + this.renderScaleY = renderScaleY; + setDirty(); + } + public void setX(final double x, final float xGravity) { this.x = x; this.xGravity = xGravity; @@ -1276,17 +1442,26 @@ public void apply() { if (dirty) { - impl_peer.setBounds((float) (Double.isNaN(x) ? 0 : x), - (float) (Double.isNaN(y) ? 0 : y), - !Double.isNaN(x), - !Double.isNaN(y), - (float) windowWidth, - (float) windowHeight, - (float) clientWidth, - (float) clientHeight, - xGravity, yGravity); - + // Snapshot values and then reset() before we call down + // as we may end up with recursive calls back up with + // new values that must be recorded as dirty. + boolean xSet = !Double.isNaN(x); + float newX = xSet ? (float) x : 0f; + boolean ySet = !Double.isNaN(y); + float newY = ySet ? (float) y : 0f; + float newWW = (float) windowWidth; + float newWH = (float) windowHeight; + float newCW = (float) clientWidth; + float newCH = (float) clientHeight; + float newXG = xGravity; + float newYG = yGravity; + float newRX = (float) renderScaleX; + float newRY = (float) renderScaleY; reset(); + impl_peer.setBounds(newX, newY, xSet, ySet, + newWW, newWH, newCW, newCH, + newXG, newYG, + newRX, newRY); } } @@ -1296,6 +1471,8 @@ } private void reset() { + renderScaleX = 0.0; + renderScaleY = 0.0; x = Double.NaN; y = Double.NaN; xGravity = 0; --- old/modules/graphics/src/main/java/javafx/scene/layout/Region.java 2016-03-30 23:38:09.000000000 -0700 +++ new/modules/graphics/src/main/java/javafx/scene/layout/Region.java 2016-03-30 23:38:08.000000000 -0700 @@ -77,6 +77,8 @@ import com.sun.javafx.sg.prism.NGNode; import com.sun.javafx.sg.prism.NGRegion; import com.sun.javafx.tk.Toolkit; +import javafx.scene.Scene; +import javafx.stage.Window; import sun.util.logging.PlatformLogger; import sun.util.logging.PlatformLogger.Level; @@ -208,7 +210,7 @@ return width; } boolean isSnapToPixel = isSnapToPixel(); - return width - snapSpace(margin.getLeft(), isSnapToPixel) - snapSpace(margin.getRight(), isSnapToPixel); + return width - snapSpaceX(margin.getLeft(), isSnapToPixel) - snapSpaceX(margin.getRight(), isSnapToPixel); } double adjustHeightByMargin(double height, Insets margin) { @@ -216,7 +218,64 @@ return height; } boolean isSnapToPixel = isSnapToPixel(); - return height - snapSpace(margin.getTop(), isSnapToPixel) - snapSpace(margin.getBottom(), isSnapToPixel); + return height - snapSpaceY(margin.getTop(), isSnapToPixel) - snapSpaceY(margin.getBottom(), isSnapToPixel); + } + + private static final boolean snapVerbose = false; + private static double getSnapScaleX(Node n) { + final double sx = _getSnapScaleXimpl(n.getScene()); + if (snapVerbose) System.out.println("static:"+n+" scale is "+sx); + return sx; + } + private static double _getSnapScaleXimpl(Scene scene) { + if (scene == null) return 1.0; + Window window = scene.getWindow(); + if (window == null) return 1.0; + return window.getRenderScaleX(); + } + + private static double getSnapScaleY(Node n) { + double sy = _getSnapScaleYimpl(n.getScene()); + if (snapVerbose) System.out.println("static:"+n+" scale is "+sy); + return sy; + } + private static double _getSnapScaleYimpl(Scene scene) { + if (scene == null) return 1.0; + Window window = scene.getWindow(); + if (window == null) return 1.0; + return window.getRenderScaleY(); + } + + private double lastScaleX = -1; + private double getSnapScaleX() { + double sx = _getSnapScaleXimpl(getScene()); + if (snapVerbose && sx != lastScaleX) { + System.out.println(this+" scale is "+sx); + lastScaleX = sx; + } + return sx; + } + + private double lastScaleY = -1; + private double getSnapScaleY() { + double sy = _getSnapScaleYimpl(getScene()); + if (snapVerbose && sy != lastScaleY) { + System.out.println(this+" scale is "+sy); + lastScaleY = sy; + } + return sy; + } + + private static double scaledRound(double value, double scale) { + return Math.round(value * scale) / scale; + } + + private static double scaledFloor(double value, double scale) { + return Math.floor(value * scale) / scale; + } + + private static double scaledCeil(double value, double scale) { + return Math.ceil(value * scale) / scale; } /** @@ -231,8 +290,15 @@ * @param snapToPixel Whether to snap to pixel * @return value either as passed in or rounded based on snapToPixel */ - private static double snapSpace(double value, boolean snapToPixel) { - return snapToPixel ? Math.round(value) : value; + private double snapSpaceX(double value, boolean snapToPixel) { + return snapToPixel ? scaledRound(value, getSnapScaleX()) : value; + } + private double snapSpaceY(double value, boolean snapToPixel) { + return snapToPixel ? scaledRound(value, getSnapScaleY()) : value; + } + + private static double snapSpace(double value, boolean snapToPixel, double snapScale) { + return snapToPixel ? scaledRound(value, snapScale) : value; } /** @@ -243,8 +309,15 @@ * @param snapToPixel Whether to snap to pixel * @return value either as passed in or ceil'd based on snapToPixel */ - private static double snapSize(double value, boolean snapToPixel) { - return snapToPixel ? Math.ceil(value) : value; + private double snapSizeX(double value, boolean snapToPixel) { + return snapToPixel ? scaledCeil(value, getSnapScaleX()) : value; + } + private double snapSizeY(double value, boolean snapToPixel) { + return snapToPixel ? scaledCeil(value, getSnapScaleY()) : value; + } + + private static double snapSize(double value, boolean snapToPixel, double snapScale) { + return snapToPixel ? scaledCeil(value, snapScale) : value; } /** @@ -255,15 +328,38 @@ * @param snapToPixel Whether to snap to pixel * @return value either as passed in or rounded based on snapToPixel */ - private static double snapPosition(double value, boolean snapToPixel) { - return snapToPixel ? Math.round(value) : value; + private double snapPositionX(double value, boolean snapToPixel) { + return snapToPixel ? scaledRound(value, getSnapScaleX()) : value; + } + private double snapPositionY(double value, boolean snapToPixel) { + return snapToPixel ? scaledRound(value, getSnapScaleY()) : value; + } + + private static double snapPosition(double value, boolean snapToPixel, double snapScale) { + return snapToPixel ? scaledRound(value, snapScale) : value; } - private static double snapPortion(double value, boolean snapToPixel) { - if (snapToPixel) { - return value == 0 ? 0 :(value > 0 ? Math.max(1, Math.floor(value)) : Math.min(-1, Math.ceil(value))); + private double snapPortionX(double value, boolean snapToPixel) { + if (!snapToPixel || value == 0) return value; + double s = getSnapScaleX(); + value *= s; + if (value > 0) { + value = Math.max(1, Math.floor(value)); + } else { + value = Math.min(-1, Math.ceil(value)); + } + return value / s; + } + private double snapPortionY(double value, boolean snapToPixel) { + if (!snapToPixel || value == 0) return value; + double s = getSnapScaleY(); + value *= s; + if (value > 0) { + value = Math.max(1, Math.floor(value)); + } else { + value = Math.min(-1, Math.ceil(value)); } - return value; + return value / s; } double getAreaBaselineOffset(List children, Callback margins, @@ -311,11 +407,14 @@ Function positionToWidth, double areaHeight, Function fillHeight, double minComplement, boolean snapToPixel) { double b = 0; + double snapScaleV = 0.0; for (int i = 0;i < children.size(); ++i) { Node n = children.get(i); + // Note: all children should be coming from the same parent so they should all have the same snapScale + if (snapToPixel && i == 0) snapScaleV = getSnapScaleY(n.getParent()); Insets margin = margins.call(n); - double top = margin != null? snapSpace(margin.getTop(), snapToPixel) : 0; - double bottom = (margin != null? snapSpace(margin.getBottom(), snapToPixel) : 0); + double top = margin != null ? snapSpace(margin.getTop(), snapToPixel, snapScaleV) : 0; + double bottom = (margin != null ? snapSpace(margin.getBottom(), snapToPixel, snapScaleV) : 0); final double bo = n.getBaselineOffset(); if (bo == BASELINE_OFFSET_SAME_AS_HEIGHT) { double alt = -1; @@ -1557,37 +1656,121 @@ } /** - * If this region's snapToPixel property is true, returns a value rounded - * to the nearest pixel, else returns the same value. + * If this region's snapToPixel property is false, this method returns the + * same value, else it tries to return a value rounded to the nearest + * pixel, but since there is no indication if the value is a vertical + * or horizontal measurement then it may be snapped to the wrong pixel + * size metric on screens with different horizontal and vertical scales. * @param value the space value to be snapped * @return value rounded to nearest pixel + * @deprecated replaced by {@code snapSpaceX()} and {@code snapSpaceY()} */ + @Deprecated protected double snapSpace(double value) { - return snapSpace(value, isSnapToPixel()); + return snapSpaceX(value, isSnapToPixel()); } /** - * If this region's snapToPixel property is true, returns a value ceiled - * to the nearest pixel, else returns the same value. + * If this region's snapToPixel property is true, returns a value rounded + * to the nearest pixel in the horizontal direction, else returns the + * same value. + * @param value the space value to be snapped + * @return value rounded to nearest pixel + */ + protected double snapSpaceX(double value) { + return snapSpaceX(value, isSnapToPixel()); + } + + /** + * If this region's snapToPixel property is true, returns a value rounded + * to the nearest pixel in the vertical direction, else returns the + * same value. + * @param value the space value to be snapped + * @return value rounded to nearest pixel + */ + protected double snapSpaceY(double value) { + return snapSpaceY(value, isSnapToPixel()); + } + + /** + * If this region's snapToPixel property is false, this method returns the + * same value, else it tries to return a value ceiled to the nearest + * pixel, but since there is no indication if the value is a vertical + * or horizontal measurement then it may be snapped to the wrong pixel + * size metric on screens with different horizontal and vertical scales. * @param value the size value to be snapped * @return value ceiled to nearest pixel + * @deprecated replaced by {@code snapSizeX()} and {@code snapSizeY()} */ + @Deprecated protected double snapSize(double value) { - return snapSize(value, isSnapToPixel()); + return snapSizeX(value, isSnapToPixel()); } /** - * If this region's snapToPixel property is true, returns a value rounded - * to the nearest pixel, else returns the same value. + * If this region's snapToPixel property is true, returns a value ceiled + * to the nearest pixel in the horizontal direction, else returns the + * same value. + * @param value the size value to be snapped + * @return value ceiled to nearest pixel + */ + protected double snapSizeX(double value) { + return snapSizeX(value, isSnapToPixel()); + } + + /** + * If this region's snapToPixel property is true, returns a value ceiled + * to the nearest pixel in the vertical direction, else returns the + * same value. + * @param value the size value to be snapped + * @return value ceiled to nearest pixel + */ + protected double snapSizeY(double value) { + return snapSizeY(value, isSnapToPixel()); + } + + /** + * If this region's snapToPixel property is false, this method returns the + * same value, else it tries to return a value rounded to the nearest + * pixel, but since there is no indication if the value is a vertical + * or horizontal measurement then it may be snapped to the wrong pixel + * size metric on screens with different horizontal and vertical scales. * @param value the position value to be snapped * @return value rounded to nearest pixel + * @deprecated replaced by {@code snapPositionX()} and {@code snapPositionY()} */ + @Deprecated protected double snapPosition(double value) { - return snapPosition(value, isSnapToPixel()); + return snapPositionX(value, isSnapToPixel()); + } + + /** + * If this region's snapToPixel property is true, returns a value rounded + * to the nearest pixel in the horizontal direction, else returns the + * same value. + * @param value the position value to be snapped + * @return value rounded to nearest pixel + */ + protected double snapPositionX(double value) { + return snapPositionX(value, isSnapToPixel()); + } + + /** + * If this region's snapToPixel property is true, returns a value rounded + * to the nearest pixel in the vertical direction, else returns the + * same value. + * @param value the position value to be snapped + * @return value rounded to nearest pixel + */ + protected double snapPositionY(double value) { + return snapPositionY(value, isSnapToPixel()); } - double snapPortion(double value) { - return snapPortion(value, isSnapToPixel()); + double snapPortionX(double value) { + return snapPortionX(value, isSnapToPixel()); + } + double snapPortionY(double value) { + return snapPortionY(value, isSnapToPixel()); } @@ -1642,28 +1825,28 @@ double computeChildMinAreaWidth(Node child, double baselineComplement, Insets margin, double height, boolean fillHeight) { final boolean snap = isSnapToPixel(); - double left = margin != null? snapSpace(margin.getLeft(), snap) : 0; - double right = margin != null? snapSpace(margin.getRight(), snap) : 0; + double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0; + double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0; double alt = -1; if (height != -1 && child.isResizable() && child.getContentBias() == Orientation.VERTICAL) { // width depends on height - double top = margin != null? snapSpace(margin.getTop(), snap) : 0; - double bottom = (margin != null? snapSpace(margin.getBottom(), snap) : 0); + double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0; + double bottom = (margin != null? snapSpaceY(margin.getBottom(), snap) : 0); double bo = child.getBaselineOffset(); final double contentHeight = bo == BASELINE_OFFSET_SAME_AS_HEIGHT && baselineComplement != -1 ? height - top - bottom - baselineComplement : height - top - bottom; if (fillHeight) { - alt = snapSize(boundedSize( + alt = snapSizeY(boundedSize( child.minHeight(-1), contentHeight, child.maxHeight(-1))); } else { - alt = snapSize(boundedSize( + alt = snapSizeY(boundedSize( child.minHeight(-1), child.prefHeight(-1), Math.min(child.maxHeight(-1), contentHeight))); } } - return left + snapSize(child.minWidth(alt)) + right; + return left + snapSizeX(child.minWidth(alt)) + right; } double computeChildMinAreaHeight(Node child, Insets margin) { @@ -1672,14 +1855,14 @@ double computeChildMinAreaHeight(Node child, double minBaselineComplement, Insets margin, double width) { final boolean snap = isSnapToPixel(); - double top =margin != null? snapSpace(margin.getTop(), snap) : 0; - double bottom = margin != null? snapSpace(margin.getBottom(), snap) : 0; + double top =margin != null? snapSpaceY(margin.getTop(), snap) : 0; + double bottom = margin != null? snapSpaceY(margin.getBottom(), snap) : 0; double alt = -1; if (child.isResizable() && child.getContentBias() == Orientation.HORIZONTAL) { // height depends on width - double left = margin != null? snapSpace(margin.getLeft(), snap) : 0; - double right = margin != null? snapSpace(margin.getRight(), snap) : 0; - alt = snapSize(width != -1? boundedSize(child.minWidth(-1), width - left - right, child.maxWidth(-1)) : + double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0; + double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0; + alt = snapSizeX(width != -1? boundedSize(child.minWidth(-1), width - left - right, child.maxWidth(-1)) : child.maxWidth(-1)); } @@ -1687,13 +1870,13 @@ if (minBaselineComplement != -1) { double baseline = child.getBaselineOffset(); if (child.isResizable() && baseline == BASELINE_OFFSET_SAME_AS_HEIGHT) { - return top + snapSize(child.minHeight(alt)) + bottom + return top + snapSizeY(child.minHeight(alt)) + bottom + minBaselineComplement; } else { return baseline + minBaselineComplement; } } else { - return top + snapSize(child.minHeight(alt)) + bottom; + return top + snapSizeY(child.minHeight(alt)) + bottom; } } @@ -1703,28 +1886,28 @@ double computeChildPrefAreaWidth(Node child, double baselineComplement, Insets margin, double height, boolean fillHeight) { final boolean snap = isSnapToPixel(); - double left = margin != null? snapSpace(margin.getLeft(), snap) : 0; - double right = margin != null? snapSpace(margin.getRight(), snap) : 0; + double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0; + double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0; double alt = -1; if (height != -1 && child.isResizable() && child.getContentBias() == Orientation.VERTICAL) { // width depends on height - double top = margin != null? snapSpace(margin.getTop(), snap) : 0; - double bottom = margin != null? snapSpace(margin.getBottom(), snap) : 0; + double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0; + double bottom = margin != null? snapSpaceY(margin.getBottom(), snap) : 0; double bo = child.getBaselineOffset(); final double contentHeight = bo == BASELINE_OFFSET_SAME_AS_HEIGHT && baselineComplement != -1 ? height - top - bottom - baselineComplement : height - top - bottom; if (fillHeight) { - alt = snapSize(boundedSize( + alt = snapSizeY(boundedSize( child.minHeight(-1), contentHeight, child.maxHeight(-1))); } else { - alt = snapSize(boundedSize( + alt = snapSizeY(boundedSize( child.minHeight(-1), child.prefHeight(-1), Math.min(child.maxHeight(-1), contentHeight))); } } - return left + snapSize(boundedSize(child.minWidth(alt), child.prefWidth(alt), child.maxWidth(alt))) + right; + return left + snapSizeX(boundedSize(child.minWidth(alt), child.prefWidth(alt), child.maxWidth(alt))) + right; } double computeChildPrefAreaHeight(Node child, Insets margin) { @@ -1733,14 +1916,14 @@ double computeChildPrefAreaHeight(Node child, double prefBaselineComplement, Insets margin, double width) { final boolean snap = isSnapToPixel(); - double top = margin != null? snapSpace(margin.getTop(), snap) : 0; - double bottom = margin != null? snapSpace(margin.getBottom(), snap) : 0; + double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0; + double bottom = margin != null? snapSpaceY(margin.getBottom(), snap) : 0; double alt = -1; if (child.isResizable() && child.getContentBias() == Orientation.HORIZONTAL) { // height depends on width - double left = margin != null ? snapSpace(margin.getLeft(), snap) : 0; - double right = margin != null ? snapSpace(margin.getRight(), snap) : 0; - alt = snapSize(boundedSize( + double left = margin != null ? snapSpaceX(margin.getLeft(), snap) : 0; + double right = margin != null ? snapSpaceX(margin.getRight(), snap) : 0; + alt = snapSizeX(boundedSize( child.minWidth(-1), width != -1 ? width - left - right : child.prefWidth(-1), child.maxWidth(-1))); } @@ -1750,7 +1933,7 @@ if (child.isResizable() && baseline == BASELINE_OFFSET_SAME_AS_HEIGHT) { // When baseline is same as height, the preferred height of the node will be above the baseline, so we need to add // the preferred complement to it - return top + snapSize(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom + return top + snapSizeY(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom + prefBaselineComplement; } else { // For all other Nodes, it's just their baseline and the complement. @@ -1758,7 +1941,7 @@ return top + baseline + prefBaselineComplement + bottom; } } else { - return top + snapSize(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom; + return top + snapSizeY(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom; } } @@ -1768,22 +1951,22 @@ return max; } final boolean snap = isSnapToPixel(); - double left = margin != null? snapSpace(margin.getLeft(), snap) : 0; - double right = margin != null? snapSpace(margin.getRight(), snap) : 0; + double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0; + double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0; double alt = -1; if (height != -1 && child.isResizable() && child.getContentBias() == Orientation.VERTICAL) { // width depends on height - double top = margin != null? snapSpace(margin.getTop(), snap) : 0; - double bottom = (margin != null? snapSpace(margin.getBottom(), snap) : 0); + double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0; + double bottom = (margin != null? snapSpaceY(margin.getBottom(), snap) : 0); double bo = child.getBaselineOffset(); final double contentHeight = bo == BASELINE_OFFSET_SAME_AS_HEIGHT && baselineComplement != -1 ? height - top - bottom - baselineComplement : height - top - bottom; if (fillHeight) { - alt = snapSize(boundedSize( + alt = snapSizeY(boundedSize( child.minHeight(-1), contentHeight, child.maxHeight(-1))); } else { - alt = snapSize(boundedSize( + alt = snapSizeY(boundedSize( child.minHeight(-1), child.prefHeight(-1), Math.min(child.maxHeight(-1), contentHeight))); @@ -1791,7 +1974,7 @@ max = child.maxWidth(alt); } // if min > max, min wins, so still need to call boundedSize() - return left + snapSize(boundedSize(child.minWidth(alt), max, Double.MAX_VALUE)) + right; + return left + snapSizeX(boundedSize(child.minWidth(alt), max, Double.MAX_VALUE)) + right; } double computeChildMaxAreaHeight(Node child, double maxBaselineComplement, Insets margin, double width) { @@ -1801,13 +1984,13 @@ } final boolean snap = isSnapToPixel(); - double top = margin != null? snapSpace(margin.getTop(), snap) : 0; - double bottom = margin != null? snapSpace(margin.getBottom(), snap) : 0; + double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0; + double bottom = margin != null? snapSpaceY(margin.getBottom(), snap) : 0; double alt = -1; if (child.isResizable() && child.getContentBias() == Orientation.HORIZONTAL) { // height depends on width - double left = margin != null? snapSpace(margin.getLeft(), snap) : 0; - double right = margin != null? snapSpace(margin.getRight(), snap) : 0; - alt = snapSize(width != -1? boundedSize(child.minWidth(-1), width - left - right, child.maxWidth(-1)) : + double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0; + double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0; + alt = snapSizeX(width != -1? boundedSize(child.minWidth(-1), width - left - right, child.maxWidth(-1)) : child.minWidth(-1)); max = child.maxHeight(alt); } @@ -1815,14 +1998,14 @@ if (maxBaselineComplement != -1) { double baseline = child.getBaselineOffset(); if (child.isResizable() && baseline == BASELINE_OFFSET_SAME_AS_HEIGHT) { - return top + snapSize(boundedSize(child.minHeight(alt), child.maxHeight(alt), Double.MAX_VALUE)) + bottom + return top + snapSizeY(boundedSize(child.minHeight(alt), child.maxHeight(alt), Double.MAX_VALUE)) + bottom + maxBaselineComplement; } else { return top + baseline + maxBaselineComplement + bottom; } } else { // if min > max, min wins, so still need to call boundedSize() - return top + snapSize(boundedSize(child.minHeight(alt), max, Double.MAX_VALUE)) + bottom; + return top + snapSizeY(boundedSize(child.minHeight(alt), max, Double.MAX_VALUE)) + bottom; } } @@ -1952,17 +2135,17 @@ final Node child = children.get(i); final double childWidth = Double.isNaN(singleChildWidth) ? childWidths[i] : singleChildWidth; Insets margin = childMargins.call(child); - final double top = margin != null? snapSpace(margin.getTop()) : 0; - final double bottom = margin != null? snapSpace(margin.getBottom()) : 0; + final double top = margin != null? snapSpaceY(margin.getTop()) : 0; + final double bottom = margin != null? snapSpaceY(margin.getBottom()) : 0; final double baseline = child.getBaselineOffset(); - final double childHeight = minimum? snapSize(child.minHeight(childWidth)) : snapSize(child.prefHeight(childWidth)); + final double childHeight = minimum? snapSizeY(child.minHeight(childWidth)) : snapSizeY(child.prefHeight(childWidth)); if (baseline == BASELINE_OFFSET_SAME_AS_HEIGHT) { maxAbove = Math.max(maxAbove, childHeight + top); } else { maxAbove = Math.max(maxAbove, baseline + top); maxBelow = Math.max(maxBelow, - snapSpace(minimum?snapSize(child.minHeight(childWidth)) : snapSize(child.prefHeight(childWidth))) - + snapSpaceY(minimum?snapSizeY(child.minHeight(childWidth)) : snapSizeY(child.prefHeight(childWidth))) - baseline + bottom); } } @@ -2062,12 +2245,14 @@ public static void positionInArea(Node child, double areaX, double areaY, double areaWidth, double areaHeight, double areaBaselineOffset, Insets margin, HPos halignment, VPos valignment, boolean isSnapToPixel) { Insets childMargin = margin != null? margin : Insets.EMPTY; + double snapScaleX = isSnapToPixel ? getSnapScaleX(child) : 1.0; + double snapScaleY = isSnapToPixel ? getSnapScaleY(child) : 1.0; position(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset, - snapSpace(childMargin.getTop(), isSnapToPixel), - snapSpace(childMargin.getRight(), isSnapToPixel), - snapSpace(childMargin.getBottom(), isSnapToPixel), - snapSpace(childMargin.getLeft(), isSnapToPixel), + snapSpace(childMargin.getTop(), isSnapToPixel, snapScaleY), + snapSpace(childMargin.getRight(), isSnapToPixel, snapScaleX), + snapSpace(childMargin.getBottom(), isSnapToPixel, snapScaleY), + snapSpace(childMargin.getLeft(), isSnapToPixel, snapScaleX), halignment, valignment, isSnapToPixel); } @@ -2296,11 +2481,13 @@ HPos halignment, VPos valignment, boolean isSnapToPixel) { Insets childMargin = margin != null ? margin : Insets.EMPTY; + double snapScaleX = isSnapToPixel ? getSnapScaleX(child) : 1.0; + double snapScaleY = isSnapToPixel ? getSnapScaleY(child) : 1.0; - double top = snapSpace(childMargin.getTop(), isSnapToPixel); - double bottom = snapSpace(childMargin.getBottom(), isSnapToPixel); - double left = snapSpace(childMargin.getLeft(), isSnapToPixel); - double right = snapSpace(childMargin.getRight(), isSnapToPixel); + double top = snapSpace(childMargin.getTop(), isSnapToPixel, snapScaleY); + double bottom = snapSpace(childMargin.getBottom(), isSnapToPixel, snapScaleY); + double left = snapSpace(childMargin.getLeft(), isSnapToPixel, snapScaleX); + double right = snapSpace(childMargin.getRight(), isSnapToPixel, snapScaleX); if (valignment == VPos.BASELINE) { double bo = child.getBaselineOffset(); @@ -2308,12 +2495,12 @@ if (child.isResizable()) { // Everything below the baseline is like an "inset". The Node with BASELINE_OFFSET_SAME_AS_HEIGHT cannot // be resized to this area - bottom += snapSpace(areaHeight - areaBaselineOffset, isSnapToPixel); + bottom += snapSpace(areaHeight - areaBaselineOffset, isSnapToPixel, snapScaleY); } else { - top = snapSpace(areaBaselineOffset - child.getLayoutBounds().getHeight(), isSnapToPixel); + top = snapSpace(areaBaselineOffset - child.getLayoutBounds().getHeight(), isSnapToPixel, snapScaleY); } } else { - top = snapSpace(areaBaselineOffset - bo, isSnapToPixel); + top = snapSpace(areaBaselineOffset - bo, isSnapToPixel, snapScaleY); } } @@ -2321,7 +2508,8 @@ if (child.isResizable()) { Vec2d size = boundedNodeSizeWithBias(child, areaWidth - left - right, areaHeight - top - bottom, fillWidth, fillHeight, TEMP_VEC2D); - child.resize(snapSize(size.x, isSnapToPixel),snapSize(size.y, isSnapToPixel)); + child.resize(snapSize(size.x, isSnapToPixel, snapScaleX), + snapSize(size.y, isSnapToPixel, snapScaleX)); } position(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset, top, right, bottom, left, halignment, valignment, isSnapToPixel); @@ -2346,8 +2534,12 @@ yoffset = topMargin + computeYOffset(areaHeight - topMargin - bottomMargin, child.getLayoutBounds().getHeight(), vpos); } - final double x = snapPosition(areaX + xoffset, isSnapToPixel); - final double y = snapPosition(areaY + yoffset, isSnapToPixel); + double x = areaX + xoffset; + double y = areaY + yoffset; + if (isSnapToPixel) { + x = snapPosition(x, true, getSnapScaleX(child)); + y = snapPosition(y, true, getSnapScaleY(child)); + } child.relocate(x,y); } --- old/apps/samples/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/SubSceneResizer.java 2016-03-30 23:38:10.000000000 -0700 +++ new/apps/samples/3DViewer/src/main/java/com/javafx/experiments/jfx3dviewer/SubSceneResizer.java 2016-03-30 23:38:10.000000000 -0700 @@ -82,8 +82,8 @@ subScene.setWidth(width); subScene.setHeight(height); } - final int controlsWidth = (int)snapSize(controlsPanel.prefWidth(-1)); - final int controlsHeight = (int)snapSize(controlsPanel.prefHeight(-1)); + final double controlsWidth = snapSizeX(controlsPanel.prefWidth(-1)); + final double controlsHeight = snapSizeY(controlsPanel.prefHeight(-1)); controlsPanel.resizeRelocate(width-controlsWidth,0,controlsWidth,controlsHeight); } } --- old/apps/samples/Ensemble8/src/app/java/ensemble/control/Popover.java 2016-03-30 23:38:11.000000000 -0700 +++ new/apps/samples/Ensemble8/src/app/java/ensemble/control/Popover.java 2016-03-30 23:38:11.000000000 -0700 @@ -33,7 +33,6 @@ import java.util.LinkedList; -import ensemble.EnsembleApp; import javafx.animation.Animation; import javafx.animation.FadeTransition; import javafx.animation.Interpolator; @@ -53,11 +52,9 @@ import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; -import javafx.scene.image.Image; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; import javafx.scene.layout.Region; -import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.scene.text.Text; import javafx.util.Duration; @@ -94,7 +91,7 @@ // private final EventHandler popoverScrollHandler; private final EventHandler popoverHideHandler; private Runnable onHideCallback = null; - private int maxPopupHeight = -1; + private double maxPopupHeight = -1; private DoubleProperty popoverHeight = new SimpleDoubleProperty(400) { @Override protected void invalidated() { @@ -229,15 +226,15 @@ maxPopupHeight = (int)getScene().getHeight()-100; } final Insets insets = getInsets(); - final int width = (int)getWidth(); - final int height = (int)getHeight(); - final int top = (int)insets.getTop(); - final int right = (int)insets.getRight(); - final int bottom = (int)insets.getBottom(); - final int left = (int)insets.getLeft(); + final double width = getWidth(); + final double height = getHeight(); + final double top = insets.getTop(); + final double right = insets.getRight(); + final double bottom = insets.getBottom(); + final double left = insets.getLeft(); - int pageWidth = width - left - right; - int pageHeight = height - top - bottom; + double pageWidth = width - left - right; + double pageHeight = height - top - bottom; frameBorder.resize(width, height); @@ -245,18 +242,18 @@ pagesClipRect.setWidth(pageWidth); pagesClipRect.setHeight(pageHeight); - int pageX = 0; + double pageX = 0; for (Node page : pagesPane.getChildren()) { page.resizeRelocate(pageX, 0, pageWidth, pageHeight); pageX += pageWidth + PAGE_GAP; } - int buttonHeight = (int)(leftButton.prefHeight(-1)); + double buttonHeight = leftButton.prefHeight(-1); if (buttonHeight < 30) buttonHeight = 30; - final int buttonTop = (int)((top-buttonHeight)/2d); - final int leftButtonWidth = (int)snapSize(leftButton.prefWidth(-1)); + final double buttonTop = (top-buttonHeight) / 2.0; + final double leftButtonWidth = snapSizeX(leftButton.prefWidth(-1)); leftButton.resizeRelocate(left, buttonTop,leftButtonWidth,buttonHeight); - final int rightButtonWidth = (int)snapSize(rightButton.prefWidth(-1)); + final double rightButtonWidth = snapSizeX(rightButton.prefWidth(-1)); rightButton.resizeRelocate(width-right-rightButtonWidth, buttonTop,rightButtonWidth,buttonHeight); final double leftButtonRight = leftButton.isVisible() ? (left + leftButtonWidth) : left; --- old/modules/controls/src/main/java/com/sun/javafx/scene/control/ContextMenuContent.java 2016-03-30 23:38:13.000000000 -0700 +++ new/modules/controls/src/main/java/com/sun/javafx/scene/control/ContextMenuContent.java 2016-03-30 23:38:13.000000000 -0700 @@ -177,36 +177,36 @@ Node n = menuItemContainer.left; if (n != null) { if (n.getContentBias() == Orientation.VERTICAL) { // width depends on height - alt = snapSize(n.prefHeight(-1)); + alt = snapSizeY(n.prefHeight(-1)); } else alt = -1; - maxLeftWidth = Math.max(maxLeftWidth, snapSize(n.prefWidth(alt))); + maxLeftWidth = Math.max(maxLeftWidth, snapSizeX(n.prefWidth(alt))); maxRowHeight = Math.max(maxRowHeight, n.prefHeight(-1)); } n = menuItemContainer.graphic; if (n != null) { if (n.getContentBias() == Orientation.VERTICAL) { // width depends on height - alt = snapSize(n.prefHeight(-1)); + alt = snapSizeY(n.prefHeight(-1)); } else alt = -1; - maxGraphicWidth = Math.max(maxGraphicWidth, snapSize(n.prefWidth(alt))); + maxGraphicWidth = Math.max(maxGraphicWidth, snapSizeX(n.prefWidth(alt))); maxRowHeight = Math.max(maxRowHeight, n.prefHeight(-1)); } n = menuItemContainer.label; if (n != null) { if (n.getContentBias() == Orientation.VERTICAL) { - alt = snapSize(n.prefHeight(-1)); + alt = snapSizeY(n.prefHeight(-1)); } else alt = -1; - maxLabelWidth = Math.max(maxLabelWidth, snapSize(n.prefWidth(alt))); + maxLabelWidth = Math.max(maxLabelWidth, snapSizeX(n.prefWidth(alt))); maxRowHeight = Math.max(maxRowHeight, n.prefHeight(-1)); } n = menuItemContainer.right; if (n != null) { if (n.getContentBias() == Orientation.VERTICAL) { // width depends on height - alt = snapSize(n.prefHeight(-1)); + alt = snapSizeY(n.prefHeight(-1)); } else alt = -1; - maxRightWidth = Math.max(maxRightWidth, snapSize(n.prefWidth(alt))); + maxRightWidth = Math.max(maxRightWidth, snapSizeX(n.prefWidth(alt))); maxRowHeight = Math.max(maxRowHeight, n.prefHeight(-1)); } } @@ -333,7 +333,7 @@ final double y = snappedTopInset(); final double w = getWidth() - x - snappedRightInset(); final double h = getHeight() - y - snappedBottomInset(); - final double contentHeight = snapSize(getContentHeight()); // itemsContainer.prefHeight(-1); + final double contentHeight = snapSizeY(getContentHeight()); // itemsContainer.prefHeight(-1); itemsContainer.resize(w,contentHeight); itemsContainer.relocate(x, y); @@ -352,18 +352,18 @@ clipRect.setHeight(h); if (upArrow.isVisible()) { - final double prefHeight = snapSize(upArrow.prefHeight(-1)); - clipRect.setHeight(snapSize(clipRect.getHeight() - prefHeight)); - clipRect.setY(snapSize(clipRect.getY()) + prefHeight); - upArrow.resize(snapSize(upArrow.prefWidth(-1)), prefHeight); + final double prefHeight = snapSizeY(upArrow.prefHeight(-1)); + clipRect.setHeight(snapSizeY(clipRect.getHeight() - prefHeight)); + clipRect.setY(snapSizeY(clipRect.getY()) + prefHeight); + upArrow.resize(snapSizeX(upArrow.prefWidth(-1)), prefHeight); positionInArea(upArrow, x, y, w, prefHeight, /*baseline ignored*/0, HPos.CENTER, VPos.CENTER); } if (downArrow.isVisible()) { - final double prefHeight = snapSize(downArrow.prefHeight(-1)); - clipRect.setHeight(snapSize(clipRect.getHeight()) - prefHeight); - downArrow.resize(snapSize(downArrow.prefWidth(-1)), prefHeight); + final double prefHeight = snapSizeY(downArrow.prefHeight(-1)); + clipRect.setHeight(snapSizeY(clipRect.getHeight()) - prefHeight); + downArrow.resize(snapSizeX(downArrow.prefWidth(-1)), prefHeight); positionInArea(downArrow, x, (y + h - prefHeight), w, prefHeight, /*baseline ignored*/0, HPos.CENTER, VPos.CENTER); } @@ -375,16 +375,16 @@ if (itemsContainer.getChildren().size() == 0) return 0; for (Node n : itemsContainer.getChildren()) { if (! n.isVisible()) continue; - prefWidth = Math.max(prefWidth, snapSize(n.prefWidth(-1))); + prefWidth = Math.max(prefWidth, snapSizeX(n.prefWidth(-1))); } - return snappedLeftInset() + snapSize(prefWidth) + snappedRightInset(); + return snappedLeftInset() + snapSizeX(prefWidth) + snappedRightInset(); } @Override protected double computePrefHeight(double width) { if (itemsContainer.getChildren().size() == 0) return 0; final double screenHeight = getScreenHeight(); final double contentHeight = getContentHeight(); // itemsContainer.prefHeight(width); - double totalHeight = snappedTopInset() + snapSize(contentHeight) + snappedBottomInset(); + double totalHeight = snappedTopInset() + snapSizeY(contentHeight) + snappedBottomInset(); // the pref height of this menu is the smaller value of the // actual pref height and the height of the screens _visual_ bounds. double prefHeight = (screenHeight <= 0) ? (totalHeight) : (Math.min(totalHeight, screenHeight)); @@ -404,7 +404,7 @@ contextMenu.getOwnerWindow().getScene() == null) { return -1; } - return snapSize(com.sun.javafx.util.Utils.getScreen( + return snapSizeY(com.sun.javafx.util.Utils.getScreen( contextMenu.getOwnerWindow().getScene().getRoot()).getVisualBounds().getHeight()); } @@ -413,7 +413,7 @@ double h = 0.0d; for (Node i : itemsContainer.getChildren()) { if (i.isVisible()) { - h += snapSize(i.prefHeight(-1)); + h += snapSizeY(i.prefHeight(-1)); } } return h; @@ -1006,8 +1006,8 @@ double yOffset = ty; for (Node n : getChildren()) { if (n.isVisible()) { - final double prefHeight = snapSize(n.prefHeight(-1)); - n.resize(snapSize(getWidth()), prefHeight); + final double prefHeight = snapSizeY(n.prefHeight(-1)); + n.resize(snapSizeX(getWidth()), prefHeight); n.relocate(snappedLeftInset(), yOffset); yOffset += prefHeight; } @@ -1069,8 +1069,8 @@ } @Override protected void layoutChildren() { - double w = snapSize(upDownArrow.prefWidth(-1)); - double h = snapSize(upDownArrow.prefHeight(-1)); + double w = snapSizeX(upDownArrow.prefWidth(-1)); + double h = snapSizeY(upDownArrow.prefHeight(-1)); upDownArrow.resize(w, h); positionInArea(upDownArrow, 0, 0, getWidth(), getHeight(), --- old/modules/controls/src/main/java/com/sun/javafx/scene/control/DatePickerContent.java 2016-03-30 23:38:14.000000000 -0700 +++ new/modules/controls/src/main/java/com/sun/javafx/scene/control/DatePickerContent.java 2016-03-30 23:38:14.000000000 -0700 @@ -143,12 +143,12 @@ // number of columns. GridPane doesn't do this with percentage // width constraints. See GridPane.adjustColumnWidths(). final int nCols = daysPerWeek + (datePicker.isShowWeekNumbers() ? 1 : 0); - final double snaphgap = snapSpace(getHgap()); - final double left = snapSpace(getInsets().getLeft()); - final double right = snapSpace(getInsets().getRight()); + final double snaphgap = snapSpaceX(getHgap()); + final double left = snapSpaceX(getInsets().getLeft()); + final double right = snapSpaceX(getInsets().getRight()); final double hgaps = snaphgap * (nCols - 1); final double contentWidth = width - left - right - hgaps; - return ((snapSize(contentWidth / nCols)) * nCols) + left + right + hgaps; + return ((snapSizeX(contentWidth / nCols)) * nCols) + left + right + hgaps; } @Override protected void layoutChildren() { --- old/modules/controls/src/main/java/com/sun/javafx/scene/control/EmbeddedTextContextMenuContent.java 2016-03-30 23:38:15.000000000 -0700 +++ new/modules/controls/src/main/java/com/sun/javafx/scene/control/EmbeddedTextContextMenuContent.java 2016-03-30 23:38:15.000000000 -0700 @@ -109,13 +109,13 @@ } @Override protected double computePrefHeight(double width) { - final double pointerHeight = snapSize(pointer.prefHeight(width)); - final double menuBoxHeight = snapSize(menuBox.prefHeight(width)); + final double pointerHeight = snapSizeY(pointer.prefHeight(width)); + final double menuBoxHeight = snapSizeY(menuBox.prefHeight(width)); return snappedTopInset() + pointerHeight + menuBoxHeight + snappedBottomInset(); } @Override protected double computePrefWidth(double height) { - final double menuBoxWidth = snapSize(menuBox.prefWidth(height)); + final double menuBoxWidth = snapSizeX(menuBox.prefWidth(height)); return snappedLeftInset() + menuBoxWidth + snappedRightInset(); } @@ -124,10 +124,10 @@ final double right = snappedRightInset(); final double top = snappedTopInset(); final double width = getWidth() - (left + right); - final double pointerWidth = snapSize(Utils.boundedSize(pointer.prefWidth(-1), pointer.minWidth(-1), pointer.maxWidth(-1))); - final double pointerHeight = snapSize(Utils.boundedSize(pointer.prefWidth(-1), pointer.minWidth(-1), pointer.maxWidth(-1))); - final double menuBoxWidth = snapSize(Utils.boundedSize(menuBox.prefWidth(-1), menuBox.minWidth(-1), menuBox.maxWidth(-1))); - final double menuBoxHeight = snapSize(Utils.boundedSize(menuBox.prefWidth(-1), menuBox.minWidth(-1), menuBox.maxWidth(-1))); + final double pointerWidth = snapSizeX(Utils.boundedSize(pointer.prefWidth(-1), pointer.minWidth(-1), pointer.maxWidth(-1))); + final double pointerHeight = snapSizeY(Utils.boundedSize(pointer.prefWidth(-1), pointer.minWidth(-1), pointer.maxWidth(-1))); + final double menuBoxWidth = snapSizeX(Utils.boundedSize(menuBox.prefWidth(-1), menuBox.minWidth(-1), menuBox.maxWidth(-1))); + final double menuBoxHeight = snapSizeY(Utils.boundedSize(menuBox.prefWidth(-1), menuBox.minWidth(-1), menuBox.maxWidth(-1))); double sceneX = 0; double screenX = 0; double pointerX = 0; --- old/modules/controls/src/main/java/javafx/scene/chart/Chart.java 2016-03-30 23:38:16.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/chart/Chart.java 2016-03-30 23:38:16.000000000 -0700 @@ -89,9 +89,9 @@ final double right = snappedRightInset(); final double width = getWidth(); final double height = getHeight(); - final double contentWidth = snapSize(width - (left + right)); - final double contentHeight = snapSize(height - (top + bottom)); - layoutChartChildren(snapPosition(top), snapPosition(left),contentWidth,contentHeight); + final double contentWidth = snapSizeX(width - (left + right)); + final double contentHeight = snapSizeY(height - (top + bottom)); + layoutChartChildren(snapPositionY(top), snapPositionX(left), contentWidth, contentHeight); } @Override public boolean usesMirroring() { return useChartContentMirroring; @@ -337,19 +337,19 @@ if (getTitle() != null) { titleLabel.setVisible(true); if (getTitleSide().equals(Side.TOP)) { - final double titleHeight = snapSize(titleLabel.prefHeight(width-left-right)); + final double titleHeight = snapSizeY(titleLabel.prefHeight(width-left-right)); titleLabel.resizeRelocate(left,top,width-left-right,titleHeight); top += titleHeight; } else if (getTitleSide().equals(Side.BOTTOM)) { - final double titleHeight = snapSize(titleLabel.prefHeight(width-left-right)); + final double titleHeight = snapSizeY(titleLabel.prefHeight(width-left-right)); titleLabel.resizeRelocate(left,height-bottom-titleHeight,width-left-right,titleHeight); bottom += titleHeight; } else if (getTitleSide().equals(Side.LEFT)) { - final double titleWidth = snapSize(titleLabel.prefWidth(height-top-bottom)); + final double titleWidth = snapSizeX(titleLabel.prefWidth(height-top-bottom)); titleLabel.resizeRelocate(left,top,titleWidth,height-top-bottom); left += titleWidth; } else if (getTitleSide().equals(Side.RIGHT)) { - final double titleWidth = snapSize(titleLabel.prefWidth(height-top-bottom)); + final double titleWidth = snapSizeX(titleLabel.prefWidth(height-top-bottom)); titleLabel.resizeRelocate(width-right-titleWidth,top,titleWidth,height-top-bottom); right += titleWidth; } @@ -362,8 +362,8 @@ boolean shouldShowLegend = isLegendVisible(); if (shouldShowLegend) { if (getLegendSide() == Side.TOP) { - final double legendHeight = snapSize(legend.prefHeight(width-left-right)); - final double legendWidth = Utils.boundedSize(snapSize(legend.prefWidth(legendHeight)), 0, width - left - right); + final double legendHeight = snapSizeY(legend.prefHeight(width-left-right)); + final double legendWidth = Utils.boundedSize(snapSizeX(legend.prefWidth(legendHeight)), 0, width - left - right); legend.resizeRelocate(left + (((width - left - right)-legendWidth)/2), top, legendWidth, legendHeight); if ((height - bottom - top - legendHeight) < MIN_HEIGHT_TO_LEAVE_FOR_CHART_CONTENT) { shouldShowLegend = false; @@ -371,8 +371,8 @@ top += legendHeight; } } else if (getLegendSide() == Side.BOTTOM) { - final double legendHeight = snapSize(legend.prefHeight(width-left-right)); - final double legendWidth = Utils.boundedSize(snapSize(legend.prefWidth(legendHeight)), 0, width - left - right); + final double legendHeight = snapSizeY(legend.prefHeight(width-left-right)); + final double legendWidth = Utils.boundedSize(snapSizeX(legend.prefWidth(legendHeight)), 0, width - left - right); legend.resizeRelocate(left + (((width - left - right)-legendWidth)/2), height-bottom-legendHeight, legendWidth, legendHeight); if ((height - bottom - top - legendHeight) < MIN_HEIGHT_TO_LEAVE_FOR_CHART_CONTENT) { shouldShowLegend = false; @@ -380,8 +380,8 @@ bottom += legendHeight; } } else if (getLegendSide() == Side.LEFT) { - final double legendWidth = snapSize(legend.prefWidth(height-top-bottom)); - final double legendHeight = Utils.boundedSize(snapSize(legend.prefHeight(legendWidth)), 0, height - top - bottom); + final double legendWidth = snapSizeX(legend.prefWidth(height-top-bottom)); + final double legendHeight = Utils.boundedSize(snapSizeY(legend.prefHeight(legendWidth)), 0, height - top - bottom); legend.resizeRelocate(left,top +(((height-top-bottom)-legendHeight)/2),legendWidth,legendHeight); if ((width - left - right - legendWidth) < MIN_WIDTH_TO_LEAVE_FOR_CHART_CONTENT) { shouldShowLegend = false; @@ -389,8 +389,8 @@ left += legendWidth; } } else if (getLegendSide() == Side.RIGHT) { - final double legendWidth = snapSize(legend.prefWidth(height-top-bottom)); - final double legendHeight = Utils.boundedSize(snapSize(legend.prefHeight(legendWidth)), 0, height - top - bottom); + final double legendWidth = snapSizeX(legend.prefWidth(height-top-bottom)); + final double legendHeight = Utils.boundedSize(snapSizeY(legend.prefHeight(legendWidth)), 0, height - top - bottom); legend.resizeRelocate(width-right-legendWidth,top +(((height-top-bottom)-legendHeight)/2),legendWidth,legendHeight); if ((width - left - right - legendWidth) < MIN_WIDTH_TO_LEAVE_FOR_CHART_CONTENT) { shouldShowLegend = false; --- old/modules/controls/src/main/java/javafx/scene/chart/XYChart.java 2016-03-30 23:38:17.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/chart/XYChart.java 2016-03-30 23:38:17.000000000 -0700 @@ -632,8 +632,8 @@ if(getData() != null) updateAxisRange(); } // snap top and left to pixels - top = snapPosition(top); - left = snapPosition(left); + top = snapPositionY(top); + left = snapPositionX(left); // get starting stuff final Axis xa = getXAxis(); final ObservableList> xaTickMarks = xa.getTickMarks(); @@ -647,12 +647,12 @@ double yAxisWidth = 0; double yAxisHeight = 0; for (int count=0; count<5; count ++) { - yAxisHeight = snapSize(height - xAxisHeight); + yAxisHeight = snapSizeY(height - xAxisHeight); if (yAxisHeight < 0) { yAxisHeight = 0; } yAxisWidth = ya.prefWidth(yAxisHeight); - xAxisWidth = snapSize(width - yAxisWidth); + xAxisWidth = snapSizeX(width - yAxisWidth); if (xAxisWidth < 0) { xAxisWidth = 0; } --- old/modules/controls/src/main/java/javafx/scene/control/Control.java 2016-03-30 23:38:19.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/control/Control.java 2016-03-30 23:38:19.000000000 -0700 @@ -575,8 +575,8 @@ if (skinBase != null) { final double x = snappedLeftInset(); final double y = snappedTopInset(); - final double w = snapSize(getWidth()) - x - snappedRightInset(); - final double h = snapSize(getHeight()) - y - snappedBottomInset(); + final double w = snapSizeX(getWidth()) - x - snappedRightInset(); + final double h = snapSizeY(getHeight()) - y - snappedBottomInset(); skinBase.layoutChildren(x, y, w, h); } else { Node n = getSkinNode(); --- old/modules/controls/src/main/java/javafx/scene/control/DialogPane.java 2016-03-30 23:38:20.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/control/DialogPane.java 2016-03-30 23:38:20.000000000 -0700 @@ -930,7 +930,7 @@ Math.max(Math.max(headerMinWidth, expandableContentMinWidth), Math.max(contentMinWidth, buttonBarMinWidth)) + snappedRightInset(); - return snapSize(minWidth); + return snapSizeX(minWidth); } /** {@inheritDoc} */ @@ -963,7 +963,7 @@ buttonBarMinHeight + snappedBottomInset(); - return snapSize(minHeight); + return snapSizeY(minHeight); } /** {@inheritDoc} */ @@ -984,7 +984,7 @@ Math.max(Math.max(headerPrefWidth, expandableContentPrefWidth), Math.max(contentPrefWidth, buttonBarPrefWidth)) + snappedRightInset(); - return snapSize(prefWidth); + return snapSizeX(prefWidth); } /** {@inheritDoc} */ @@ -1016,7 +1016,7 @@ buttonBarPrefHeight + snappedBottomInset(); - return snapSize(prefHeight); + return snapSizeY(prefHeight); } --- old/modules/controls/src/main/java/javafx/scene/control/skin/ColorPalette.java 2016-03-30 23:38:22.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/control/skin/ColorPalette.java 2016-03-30 23:38:22.000000000 -0700 @@ -187,8 +187,8 @@ xAdjust = focusedSquare.getWidth() / 2.0 + scaleAdjust; } - hoverSquare.setLayoutX(snapPosition(x) - xAdjust); - hoverSquare.setLayoutY(snapPosition(y) - focusedSquare.getHeight() / 2.0 + (hoverSquare.getScaleY() == 1.0 ? 0 : focusedSquare.getHeight() / 4.0)); + hoverSquare.setLayoutX(snapPositionX(x) - xAdjust); + hoverSquare.setLayoutY(snapPositionY(y) - focusedSquare.getHeight() / 2.0 + (hoverSquare.getScaleY() == 1.0 ? 0 : focusedSquare.getHeight() / 4.0)); } private void buildCustomColors() { --- old/modules/controls/src/main/java/javafx/scene/control/skin/NestedTableColumnHeader.java 2016-03-30 23:38:23.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/control/skin/NestedTableColumnHeader.java 2016-03-30 23:38:23.000000000 -0700 @@ -297,11 +297,11 @@ TableColumnHeader n = getColumnHeaders().get(i); if (! n.isVisible()) continue; - double prefWidth = snapSize(n.prefWidth(-1)); + double prefWidth = snapSizeX(n.prefWidth(-1)); // double prefHeight = n.prefHeight(-1); // position the column header in the default location... - n.resize(prefWidth, snapSize(h - labelHeight)); + n.resize(prefWidth, snapSizeY(h - labelHeight)); n.relocate(x, labelHeight + snappedTopInset()); // // ...but, if there are no children of this column, we should ensure @@ -335,7 +335,7 @@ if (getColumns() != null) { for (TableColumnHeader c : getColumnHeaders()) { if (c.isVisible()) { - width += snapSize(c.computePrefWidth(height)); + width += snapSizeX(c.computePrefWidth(height)); } } } --- old/modules/controls/src/main/java/javafx/scene/control/skin/ScrollBarSkin.java 2016-03-30 23:38:25.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/control/skin/ScrollBarSkin.java 2016-03-30 23:38:24.000000000 -0700 @@ -660,10 +660,10 @@ final double left = snappedLeftInset(); final double bottom = snappedBottomInset(); final double right = snappedRightInset(); - final double aw = snapSize(arrow.prefWidth(-1)); - final double ah = snapSize(arrow.prefHeight(-1)); - final double yPos = snapPosition((getHeight() - (top + bottom + ah)) / 2.0); - final double xPos = snapPosition((getWidth() - (left + right + aw)) / 2.0); + final double aw = snapSizeX(arrow.prefWidth(-1)); + final double ah = snapSizeY(arrow.prefHeight(-1)); + final double yPos = snapPositionY((getHeight() - (top + bottom + ah)) / 2.0); + final double xPos = snapPositionX((getWidth() - (left + right + aw)) / 2.0); arrow.resizeRelocate(xPos + left, yPos + top, aw, ah); } @@ -678,14 +678,14 @@ @Override protected double computePrefWidth(double height) { final double left = snappedLeftInset(); final double right = snappedRightInset(); - final double aw = snapSize(arrow.prefWidth(-1)); + final double aw = snapSizeX(arrow.prefWidth(-1)); return left + aw + right; } @Override protected double computePrefHeight(double width) { final double top = snappedTopInset(); final double bottom = snappedBottomInset(); - final double ah = snapSize(arrow.prefHeight(-1)); + final double ah = snapSizeY(arrow.prefHeight(-1)); return top + ah + bottom; } } --- old/modules/controls/src/main/java/javafx/scene/control/skin/SplitPaneSkin.java 2016-03-30 23:38:26.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/control/skin/SplitPaneSkin.java 2016-03-30 23:38:26.000000000 -0700 @@ -1189,11 +1189,11 @@ } @Override protected double computeMaxWidth(double height) { - return snapSize(content.maxWidth(height)); + return snapSizeX(content.maxWidth(height)); } @Override protected double computeMaxHeight(double width) { - return snapSize(content.maxHeight(width)); + return snapSizeY(content.maxHeight(width)); } } } --- old/modules/controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java 2016-03-30 23:38:27.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/control/skin/TableColumnHeader.java 2016-03-30 23:38:27.000000000 -0700 @@ -361,7 +361,7 @@ } double sortWidth = 0; - double w = snapSize(getWidth()) - (snappedLeftInset() + snappedRightInset()); + double w = snapSizeX(getWidth()) - (snappedLeftInset() + snappedRightInset()); double h = getHeight() - (snappedTopInset() + snappedBottomInset()); double x = w; --- old/modules/controls/src/main/java/javafx/scene/control/skin/TableHeaderRow.java 2016-03-30 23:38:28.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/control/skin/TableHeaderRow.java 2016-03-30 23:38:28.000000000 -0700 @@ -332,9 +332,9 @@ /** {@inheritDoc} */ @Override protected void layoutChildren() { double x = scrollX; - double headerWidth = snapSize(getRootHeader().prefWidth(-1)); + double headerWidth = snapSizeX(getRootHeader().prefWidth(-1)); double prefHeight = getHeight() - snappedTopInset() - snappedBottomInset(); - double cornerWidth = snapSize(flow.getVbar().prefWidth(-1)); + double cornerWidth = snapSizeX(flow.getVbar().prefWidth(-1)); // position the main nested header getRootHeader().resizeRelocate(x, snappedTopInset(), headerWidth, prefHeight); @@ -399,8 +399,8 @@ this.tableWidth = 0; } else { Insets insets = c.getInsets() == null ? Insets.EMPTY : c.getInsets(); - double padding = snapSize(insets.getLeft()) + snapSize(insets.getRight()); - this.tableWidth = snapSize(c.getWidth()) - padding; + double padding = snapSizeX(insets.getLeft()) + snapSizeX(insets.getRight()); + this.tableWidth = snapSizeX(c.getWidth()) - padding; } clip.setWidth(tableWidth); --- old/modules/controls/src/main/java/javafx/scene/control/skin/VirtualFlow.java 2016-03-30 23:38:29.000000000 -0700 +++ new/modules/controls/src/main/java/javafx/scene/control/skin/VirtualFlow.java 2016-03-30 23:38:29.000000000 -0700 @@ -1848,9 +1848,9 @@ private void positionCell(T cell, double position) { if (isVertical()) { cell.setLayoutX(0); - cell.setLayoutY(snapSize(position)); + cell.setLayoutY(snapSizeY(position)); } else { - cell.setLayoutX(snapSize(position)); + cell.setLayoutX(snapSizeX(position)); cell.setLayoutY(0); } } @@ -2239,8 +2239,8 @@ private void updateViewportDimensions() { final boolean isVertical = isVertical(); - final double breadthBarLength = snapSize(isVertical ? hbar.prefHeight(-1) : vbar.prefWidth(-1)); - final double lengthBarBreadth = snapSize(isVertical ? vbar.prefWidth(-1) : hbar.prefHeight(-1)); + final double breadthBarLength = isVertical ? snapSizeY(hbar.prefHeight(-1)) : snapSizeX(vbar.prefWidth(-1)); + final double lengthBarBreadth = isVertical ? snapSizeX(vbar.prefWidth(-1)) : snapSizeY(hbar.prefHeight(-1)); setViewportBreadth((isVertical ? getWidth() : getHeight()) - (needLengthBar ? lengthBarBreadth : 0)); setViewportLength((isVertical ? getHeight() : getWidth()) - (needBreadthBar ? breadthBarLength : 0)); @@ -2431,8 +2431,8 @@ } } - clipView.resize(snapSize(isVertical ? viewportBreadth : viewportLength), - snapSize(isVertical ? viewportLength : viewportBreadth)); + clipView.resize(snapSizeX(isVertical ? viewportBreadth : viewportLength), + snapSizeY(isVertical ? viewportLength : viewportBreadth)); // If the viewportLength becomes large enough that all cells fit // within the viewport, then we want to update the value to match. --- old/modules/graphics/src/main/java/com/sun/glass/events/WindowEvent.java 2016-03-30 23:38:30.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/events/WindowEvent.java 2016-03-30 23:38:30.000000000 -0700 @@ -27,6 +27,7 @@ public class WindowEvent { final static public int RESIZE = 511; final static public int MOVE = 512; + final static public int RESCALE = 513; final static public int CLOSE = 521; final static public int DESTROY = 522; @@ -51,6 +52,8 @@ return "RESIZE"; case WindowEvent.MOVE: return "MOVE"; + case WindowEvent.RESCALE: + return "RESCALE"; case WindowEvent.CLOSE: return "CLOSE"; case WindowEvent.DESTROY: --- old/modules/graphics/src/main/java/com/sun/glass/ui/Application.java 2016-03-30 23:38:32.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/Application.java 2016-03-30 23:38:31.000000000 -0700 @@ -621,12 +621,12 @@ public abstract Pixels createPixels(int width, int height, ByteBuffer data); public abstract Pixels createPixels(int width, int height, IntBuffer data); - public abstract Pixels createPixels(int width, int height, IntBuffer data, float scale); + public abstract Pixels createPixels(int width, int height, IntBuffer data, float scalex, float scaley); protected abstract int staticPixels_getNativeFormat(); /* utility method called from native code */ - static Pixels createPixels(int width, int height, int[] data, float scale) { - return Application.GetApplication().createPixels(width, height, IntBuffer.wrap(data), scale); + static Pixels createPixels(int width, int height, int[] data, float scalex, float scaley) { + return Application.GetApplication().createPixels(width, height, IntBuffer.wrap(data), scalex, scaley); } /* utility method called from native code */ @@ -636,8 +636,11 @@ for (Screen s : Screen.getScreens()) { final int sx = s.getX(), sy = s.getY(), sw = s.getWidth(), sh = s.getHeight(); if (x < (sx + sw) && (x + w) > sx && y < (sy + sh) && (y + h) > sy) { - if (scale < s.getRenderScale()) { - scale = s.getRenderScale(); + if (scale < s.getRecommendedOutputScaleX()) { + scale = s.getRecommendedOutputScaleX(); + } + if (scale < s.getRecommendedOutputScaleY()) { + scale = s.getRecommendedOutputScaleY(); } } } --- old/modules/graphics/src/main/java/com/sun/glass/ui/Pixels.java 2016-03-30 23:38:33.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/Pixels.java 2016-03-30 23:38:33.000000000 -0700 @@ -80,7 +80,8 @@ protected final ByteBuffer bytes; protected final IntBuffer ints; - private final float scale; + private final float scalex; + private final float scaley; protected Pixels(final int width, final int height, final ByteBuffer pixels) { this.width = width; @@ -92,7 +93,8 @@ } this.ints = null; - this.scale = 1.0f; + this.scalex = 1.0f; + this.scaley = 1.0f; } protected Pixels(final int width, final int height, IntBuffer pixels) { @@ -105,10 +107,11 @@ } this.bytes = null; - this.scale = 1.0f; + this.scalex = 1.0f; + this.scaley = 1.0f; } - protected Pixels(final int width, final int height, IntBuffer pixels, float scale) { + protected Pixels(final int width, final int height, IntBuffer pixels, float scalex, float scaley) { this.width = width; this.height = height; this.bytesPerComponent = 4; @@ -118,16 +121,26 @@ } this.bytes = null; - this.scale = scale; + this.scalex = scalex; + this.scaley = scaley; } - public final float getScale() { + public final float getScaleX() { Application.checkEventThread(); - return this.scale; + return this.scalex; } - public final float getScaleUnsafe() { - return this.scale; + public final float getScaleY() { + Application.checkEventThread(); + return this.scaley; + } + + public final float getScaleXUnsafe() { + return this.scalex; + } + + public final float getScaleYUnsafe() { + return this.scaley; } public final int getWidth() { --- old/modules/graphics/src/main/java/com/sun/glass/ui/Screen.java 2016-03-30 23:38:34.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/Screen.java 2016-03-30 23:38:34.000000000 -0700 @@ -85,6 +85,11 @@ private final int width; private final int height; + private final int platformX; + private final int platformY; + private final int platformWidth; + private final int platformHeight; + private final int visibleX; private final int visibleY; private final int visibleWidth; @@ -93,10 +98,12 @@ private final int resolutionX; private final int resolutionY; - private final float uiScale; - private final float renderScale; + private final float platformScaleX; + private final float platformScaleY; + private final float outputScaleX; + private final float outputScaleY; - protected Screen( + public Screen( long nativePtr, int depth, @@ -105,31 +112,10 @@ int width, int height, - int visibleX, - int visibleY, - int visibleWidth, - int visibleHeight, - - int resolutionX, - int resolutionY, - - float renderScale - ) { - this(nativePtr, - depth, x, y, width, height, - visibleX, visibleY, visibleWidth, visibleHeight, - resolutionX, resolutionY, - 1.0f, renderScale); - } - - protected Screen( - long nativePtr, - - int depth, - int x, - int y, - int width, - int height, + int platformX, + int platformY, + int platformWidth, + int platformHeight, int visibleX, int visibleY, @@ -139,8 +125,10 @@ int resolutionX, int resolutionY, - float uiScale, - float renderScale + float platformScaleX, + float platformScaleY, + float outputScaleX, + float outputScaleY ) { this.ptr = nativePtr; @@ -151,6 +139,11 @@ this.width = width; this.height = height; + this.platformX = platformX; + this.platformY = platformY; + this.platformWidth = platformWidth; + this.platformHeight = platformHeight; + this.visibleX = visibleX; this.visibleY = visibleY; this.visibleWidth = visibleWidth; @@ -163,8 +156,10 @@ this.resolutionY = resolutionY; } - this.uiScale = uiScale; - this.renderScale = renderScale; + this.platformScaleX = platformScaleX; + this.platformScaleY = platformScaleY; + this.outputScaleX = outputScaleX; + this.outputScaleY = outputScaleY; } /** @@ -205,6 +200,72 @@ /** * Could be called from any thread */ + public int getPlatformX() { + return this.platformX; + } + + /** + * Could be called from any thread + */ + public int getPlatformY() { + return this.platformY; + } + + /** + * Could be called from any thread + */ + public int getPlatformWidth() { + return this.platformWidth; + } + + /** + * Could be called from any thread + */ + public int getPlatformHeight() { + return this.platformHeight; + } + + /** + * Returns the horizontal scaling of the UI (window sizes and event + * coordinates) from FX logical units to the platform units. + * Could be called from any thread + * @return platform X scaling + */ + public float getPlatformScaleX() { + return this.platformScaleX; + } + + /** + * Returns the vertical scaling of the UI (window sizes and event + * coordinates) from FX logical units to the platform units. + * Could be called from any thread + * @return platform Y scaling + */ + public float getPlatformScaleY() { + return this.platformScaleY; + } + + /** + * Returns the recommended horizontal scaling for the rendered frames. + * Could be called from any thread + * @return recommended render X scaling + */ + public float getRecommendedOutputScaleX() { + return this.outputScaleX; + } + + /** + * Returns the recommended vertical scaling for the rendered frames. + * Could be called from any thread + * @return recommended render Y scaling + */ + public float getRecommendedOutputScaleY() { + return this.outputScaleY; + } + + /** + * Could be called from any thread + */ public int getVisibleX() { return this.visibleX; } @@ -245,24 +306,6 @@ } /** - * Returns the scaling of the UI (window sizes and event coordinates) - * on the screen. - * Could be called from any thread - */ - public float getUIScale() { - return this.uiScale; - } - - /** - * Returns the recommended scaling for rendering an image for this - * screen, potentially larger than {@link #getUIScale()}. - * Could be called from any thread - */ - public float getRenderScale() { - return this.renderScale; - } - - /** * Could be called from any thread */ public long getNativeScreen() { @@ -341,12 +384,18 @@ " y:"+getY()+"\n"+ " width:"+getWidth()+"\n"+ " height:"+getHeight()+"\n"+ + " platformX:"+getPlatformX()+"\n"+ + " platformY:"+getPlatformY()+"\n"+ + " platformWidth:"+getPlatformWidth()+"\n"+ + " platformHeight:"+getPlatformHeight()+"\n"+ " visibleX:"+getVisibleX()+"\n"+ " visibleY:"+getVisibleY()+"\n"+ " visibleWidth:"+getVisibleWidth()+"\n"+ " visibleHeight:"+getVisibleHeight()+"\n"+ - " uiScale:"+getUIScale()+"\n"+ - " RenderScale:"+getRenderScale()+"\n"+ + " platformScaleX:"+getPlatformScaleX()+"\n"+ + " platformScaleY:"+getPlatformScaleY()+"\n"+ + " outputScaleX:"+getRecommendedOutputScaleX()+"\n"+ + " outputScaleY:"+getRecommendedOutputScaleY()+"\n"+ " resolutionX:"+getResolutionX()+"\n"+ " resolutionY:"+getResolutionY()+"\n"; } @@ -369,8 +418,10 @@ && visibleHeight == screen.visibleHeight && resolutionX == screen.resolutionX && resolutionY == screen.resolutionY - && Float.compare(screen.uiScale, uiScale) == 0 - && Float.compare(screen.renderScale, renderScale) == 0; + && Float.compare(screen.platformScaleX, platformScaleX) == 0 + && Float.compare(screen.platformScaleY, platformScaleY) == 0 + && Float.compare(screen.outputScaleX, outputScaleX) == 0 + && Float.compare(screen.outputScaleY, outputScaleY) == 0; } @Override public int hashCode() { @@ -388,8 +439,10 @@ result = 31 * result + visibleHeight; result = 31 * result + resolutionX; result = 31 * result + resolutionY; - result = 31 * result + (uiScale != +0.0f ? Float.floatToIntBits(uiScale) : 0); - result = 31 * result + (renderScale != +0.0f ? Float.floatToIntBits(renderScale) : 0); + result = 31 * result + (platformScaleX != +0.0f ? Float.floatToIntBits(platformScaleX) : 0); + result = 31 * result + (platformScaleY != +0.0f ? Float.floatToIntBits(platformScaleY) : 0); + result = 31 * result + (outputScaleX != +0.0f ? Float.floatToIntBits(outputScaleX) : 0); + result = 31 * result + (outputScaleY != +0.0f ? Float.floatToIntBits(outputScaleY) : 0); return result; } } --- old/modules/graphics/src/main/java/com/sun/glass/ui/Window.java 2016-03-30 23:38:35.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/Window.java 2016-03-30 23:38:35.000000000 -0700 @@ -206,8 +206,12 @@ private int width = 0; private int height = 0; private float alpha = 1.0f; - private float platformScale = 1.0f; - private float renderScale = 1.0f; + private float platformScaleX = 1.0f; + private float platformScaleY = 1.0f; + private float outputScaleX = 1.0f; + private float outputScaleY = 1.0f; + private float renderScaleX = 1.0f; + private float renderScaleY = 1.0f; // This is a workaround for RT-15970: as for embedded windows we don't // receive any MOVE notifications from the native platform, we poll @@ -269,6 +273,12 @@ this.isDecorated = (this.styleMask & Window.TITLED) != 0; this.screen = screen != null ? screen : Screen.getMainScreen(); + if (PrismSettings.allowHiDPIScaling) { + this.platformScaleX = this.screen.getPlatformScaleX(); + this.platformScaleY = this.screen.getPlatformScaleY(); + this.outputScaleX = this.screen.getRecommendedOutputScaleX(); + this.outputScaleY = this.screen.getRecommendedOutputScaleY(); + } this.ptr = _createWindow(owner != null ? owner.getNativeHandle() : 0L, this.screen.getNativeScreen(), this.styleMask); @@ -466,38 +476,67 @@ return isMaximized(); } - public void setPlatformScale(float platformScale) { + protected void notifyScaleChanged(float platformScaleX, float platformScaleY, + float outputScaleX, float outputScaleY) + { if (!PrismSettings.allowHiDPIScaling) return; - this.platformScale = platformScale; + this.platformScaleX = platformScaleX; + this.platformScaleY = platformScaleY; + this.outputScaleX = outputScaleX; + this.outputScaleY = outputScaleY; + notifyRescale(); } /** - * Return the scale used to communicate window locations, sizes, and event - * coordinates to/from the platform. - * @return the platform scaling for screen locations + * Return the horizontal scale used to communicate window locations, + * sizes, and event coordinates to/from the platform. + * @return the horizontal platform scaling for screen locations */ - public final float getPlatformScale() { - return platformScale; + public final float getPlatformScaleX() { + return platformScaleX; + } + + /** + * Return the vertical scale used to communicate window locations, + * sizes, and event coordinates to/from the platform. + * @return the vertical platform scaling for screen locations + */ + public final float getPlatformScaleY() { + return platformScaleY; + } + + public void setRenderScaleX(float renderScaleX) { + if (!PrismSettings.allowHiDPIScaling) return; + this.renderScaleX = renderScaleX; } - public void setRenderScale(float renderScale) { + public void setRenderScaleY(float renderScaleY) { if (!PrismSettings.allowHiDPIScaling) return; - this.renderScale = renderScale; + this.renderScaleY = renderScaleY; } /** - * Return the scale that should be used to render content on this window. - * This is usually similar to the platform scale, but may be different - * depending on how the platform manages events vs. rendering buffers - * and/or whether the system can handle non-integer rendering scales. - * @return the pixel scaling to be used during rendering + * Return the horizontal scale used for rendering the back buffer. + * @return the horizontal scaling for rendering */ - public final float getRenderScale() { - return renderScale; + public final float getRenderScaleX() { + return renderScaleX; } - public float getOutputScale() { - return platformScale; + /** + * Return the vertical scale used for rendering to the back buffer. + * @return the vertical scaling for rendering + */ + public final float getRenderScaleY() { + return renderScaleY; + } + + public float getOutputScaleX() { + return outputScaleX; + } + + public float getOutputScaleY() { + return outputScaleY; } protected abstract int _getEmbeddedX(long ptr); @@ -1194,6 +1233,10 @@ handleWindowEvent(System.nanoTime(), WindowEvent.MOVE); } + protected void notifyRescale() { + handleWindowEvent(System.nanoTime(), WindowEvent.RESCALE); + } + protected void notifyMoveToAnotherScreen(Screen newScreen) { setScreen(newScreen); } --- old/modules/graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java 2016-03-30 23:38:37.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/gtk/GtkApplication.java 2016-03-30 23:38:37.000000000 -0700 @@ -273,8 +273,8 @@ } @Override - public Pixels createPixels(int width, int height, IntBuffer data, float scale) { - return new GtkPixels(width, height, data, scale); + public Pixels createPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + return new GtkPixels(width, height, data, scalex, scaley); } @Override --- old/modules/graphics/src/main/java/com/sun/glass/ui/gtk/GtkPixels.java 2016-03-30 23:38:38.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/gtk/GtkPixels.java 2016-03-30 23:38:38.000000000 -0700 @@ -39,8 +39,8 @@ super(width, height, data); } - public GtkPixels(int width, int height, IntBuffer data, float scale) { - super(width, height, data, scale); + public GtkPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + super(width, height, data, scalex, scaley); } @Override --- old/modules/graphics/src/main/java/com/sun/glass/ui/ios/IosApplication.java 2016-03-30 23:38:40.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/ios/IosApplication.java 2016-03-30 23:38:39.000000000 -0700 @@ -136,8 +136,8 @@ } @Override - public Pixels createPixels(int width, int height, IntBuffer data, float scale) { - return new IosPixels(width, height, data, scale); + public Pixels createPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + return new IosPixels(width, height, data, scalex, scaley); } @Override --- old/modules/graphics/src/main/java/com/sun/glass/ui/ios/IosPixels.java 2016-03-30 23:38:41.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/ios/IosPixels.java 2016-03-30 23:38:41.000000000 -0700 @@ -42,8 +42,8 @@ super(width, height, data); } - protected IosPixels(int width, int height, IntBuffer data, float scale) { - super(width, height, data, scale); + protected IosPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + super(width, height, data, scalex, scaley); } @Override --- old/modules/graphics/src/main/java/com/sun/glass/ui/lens/LensApplication.java 2016-03-30 23:38:42.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/lens/LensApplication.java 2016-03-30 23:38:42.000000000 -0700 @@ -1682,8 +1682,8 @@ } @Override - public Pixels createPixels(int width, int height, IntBuffer data, float scale) { - return new LensPixels(width, height, data, scale); + public Pixels createPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + return new LensPixels(width, height, data, scalex, scaley); } @Override --- old/modules/graphics/src/main/java/com/sun/glass/ui/lens/LensPixels.java 2016-03-30 23:38:44.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/lens/LensPixels.java 2016-03-30 23:38:43.000000000 -0700 @@ -40,8 +40,8 @@ super(width, height, data); } - protected LensPixels(int width, int height, IntBuffer data, float scale) { - super(width, height, data, scale); + protected LensPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + super(width, height, data, scalex, scaley); } static int getNativeFormat_impl() { --- old/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacApplication.java 2016-03-30 23:38:45.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacApplication.java 2016-03-30 23:38:45.000000000 -0700 @@ -228,8 +228,8 @@ } @Override - public Pixels createPixels(int width, int height, IntBuffer data, float scale) { - return new MacPixels(width, height, data, scale); + public Pixels createPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + return new MacPixels(width, height, data, scalex, scaley); } @Override protected int staticPixels_getNativeFormat() { --- old/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacPixels.java 2016-03-30 23:38:46.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacPixels.java 2016-03-30 23:38:46.000000000 -0700 @@ -57,8 +57,8 @@ super(width, height, data); } - protected MacPixels(int width, int height, IntBuffer data, float scale) { - super(width, height, data, scale); + protected MacPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + super(width, height, data, scalex, scaley); } @Override --- old/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacView.java 2016-03-30 23:38:47.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacView.java 2016-03-30 23:38:47.000000000 -0700 @@ -26,6 +26,7 @@ import com.sun.glass.ui.Pixels; import com.sun.glass.ui.View; +import com.sun.glass.ui.Window; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; @@ -81,26 +82,51 @@ @Override protected void _uploadPixels(long ptr, Pixels pixels) { Buffer data = pixels.getPixels(); if (data.isDirect() == true) { - _uploadPixelsDirect(ptr, data, pixels.getWidth(), pixels.getHeight(), pixels.getScale()); + _uploadPixelsDirect(ptr, data, pixels.getWidth(), pixels.getHeight(), pixels.getScaleX(), pixels.getScaleY()); } else if (data.hasArray() == true) { if (pixels.getBytesPerComponent() == 1) { ByteBuffer bytes = (ByteBuffer)data; _uploadPixelsByteArray(ptr, bytes.array(), bytes.arrayOffset(), - pixels.getWidth(), pixels.getHeight(), pixels.getScale()); + pixels.getWidth(), pixels.getHeight(), pixels.getScaleX(), pixels.getScaleY()); } else { IntBuffer ints = (IntBuffer)data; _uploadPixelsIntArray(ptr, ints.array(), ints.arrayOffset(), - pixels.getWidth(), pixels.getHeight(), pixels.getScale()); + pixels.getWidth(), pixels.getHeight(), pixels.getScaleX(), pixels.getScaleY()); } } else { // gznote: what are the circumstances under which this can happen? _uploadPixelsDirect(ptr, pixels.asByteBuffer(), - pixels.getWidth(), pixels.getHeight(), pixels.getScale()); + pixels.getWidth(), pixels.getHeight(), pixels.getScaleX(), pixels.getScaleY()); } } - native void _uploadPixelsDirect(long viewPtr, Buffer pixels, int width, int height, float scale); - native void _uploadPixelsByteArray(long viewPtr, byte[] pixels, int offset, int width, int height, float scale); - native void _uploadPixelsIntArray(long viewPtr, int[] pixels, int offset, int width, int height, float scale); + native void _uploadPixelsDirect(long viewPtr, Buffer pixels, int width, int height, float scaleX, float scaleY); + native void _uploadPixelsByteArray(long viewPtr, byte[] pixels, int offset, int width, int height, float scaleX, float scaleY); + native void _uploadPixelsIntArray(long viewPtr, int[] pixels, int offset, int width, int height, float scaleX, float scaleY); + + @Override + protected void notifyResize(int width, int height) { + Window w = getWindow(); + float sx = (w == null) ? 1.0f : w.getPlatformScaleX(); + float sy = (w == null) ? 1.0f : w.getPlatformScaleY(); + width = Math.round(width * sx); + height = Math.round(height * sy); + super.notifyResize(width, height); + } + + @Override + protected void notifyMouse(int type, int button, int x, int y, int xAbs, + int yAbs, int modifiers, boolean isPopupTrigger, + boolean isSynthesized) { + Window w = getWindow(); + float sx = (w == null) ? 1.0f : w.getPlatformScaleX(); + float sy = (w == null) ? 1.0f : w.getPlatformScaleY(); + x = Math.round(x * sx); + y = Math.round(y * sy); + xAbs = Math.round(xAbs * sx); + yAbs = Math.round(yAbs * sy); + super.notifyMouse(type, button, x, y, xAbs, yAbs, modifiers, + isPopupTrigger, isSynthesized); + } @Override protected long _getNativeView(long ptr) { return ptr; --- old/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacWindow.java 2016-03-30 23:38:48.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/mac/MacWindow.java 2016-03-30 23:38:48.000000000 -0700 @@ -46,8 +46,6 @@ protected MacWindow(Window owner, Screen screen, int styleMask) { super(owner, screen, styleMask); - setPlatformScale(screen.getUIScale()); - setRenderScale(screen.getRenderScale()); } protected MacWindow(long parent) { super(parent); @@ -57,14 +55,10 @@ protected void setScreen(Screen screen) { // SceneState will be called to update with new scale values // before we return from super.setScreen()... - setRenderScale(screen.getUIScale()); - setRenderScale(screen.getRenderScale()); super.setScreen(screen); - } - - @Override - public float getOutputScale() { - return getRenderScale(); + notifyScaleChanged(1.0f, 1.0f, + screen.getRecommendedOutputScaleX(), + screen.getRecommendedOutputScaleY()); } @Override native protected long _createWindow(long ownerPtr, long screenPtr, int mask); @@ -74,7 +68,22 @@ @Override native protected boolean _setMenubar(long ptr, long menubarPtr); @Override native protected boolean _minimize(long ptr, boolean minimize); @Override native protected boolean _maximize(long ptr, boolean maximize, boolean wasMaximized); - @Override native protected void _setBounds(long ptr, int x, int y, boolean xSet, boolean ySet, int w, int h, int cw, int ch, float xGravity, float yGravity); + @Override protected void _setBounds(long ptr, + int x, int y, boolean xSet, boolean ySet, + int w, int h, int cw, int ch, + float xGravity, float yGravity) + { + float sx = getPlatformScaleX(); + float sy = getPlatformScaleY(); + if (xSet) x = Math.round( x / sx); + if (ySet) y = Math.round( y / sy); + if ( w > 0) w = Math.round( w / sx); + if ( h > 0) h = Math.round( h / sy); + if (cw > 0) cw = Math.round(cw / sx); + if (ch > 0) ch = Math.round(ch / sy); + _setBounds2(ptr, x, y, xSet, ySet, w, h, cw, ch, xGravity, yGravity); + } + native protected void _setBounds2(long ptr, int x, int y, boolean xSet, boolean ySet, int w, int h, int cw, int ch, float xGravity, float yGravity); @Override native protected boolean _setVisible(long ptr, boolean visible); @Override native protected boolean _setResizable(long ptr, boolean resizable); @@ -109,6 +118,13 @@ @Override native protected int _getEmbeddedY(long ptr); @Override + protected void notifyResize(int type, int width, int height) { + width = Math.round( width * getPlatformScaleX()); + height = Math.round(height * getPlatformScaleY()); + super.notifyResize(type, width, height); + } + + @Override protected void _setCursor(long ptr, Cursor cursor) { ((MacCursor)cursor).set(); } --- old/modules/graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java 2016-03-30 23:38:50.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java 2016-03-30 23:38:50.000000000 -0700 @@ -198,8 +198,9 @@ @Override public Pixels createPixels(int width, int height, IntBuffer data, - float scale) { - return new MonoclePixels(width, height, data, scale); + float scalex, float scaley) + { + return new MonoclePixels(width, height, data, scalex, scaley); } @Override @@ -219,49 +220,20 @@ @Override protected Screen[] staticScreen_getScreens() { - Screen screen = null; - try { - NativeScreen ns = platform.getScreen(); - Constructor c = AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public Constructor run() { - try { - Constructor c = Screen.class.getDeclaredConstructor( - Long.TYPE, - Integer.TYPE, - Integer.TYPE, Integer.TYPE, - Integer.TYPE, Integer.TYPE, - Integer.TYPE, Integer.TYPE, - Integer.TYPE, Integer.TYPE, - Integer.TYPE, Integer.TYPE, Float.TYPE); - c.setAccessible(true); - return c; - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - }); - if (c != null) { - screen = (Screen) c.newInstance( - 1l, // dummy native pointer; - ns.getDepth(), - 0, 0, ns.getWidth(), ns.getHeight(), - 0, 0, ns.getWidth(), ns.getHeight(), - ns.getDPI(), ns.getDPI(), - ns.getScale()); - // Move the cursor to the middle of the screen - MouseState mouseState = new MouseState(); - mouseState.setX(ns.getWidth() / 2); - mouseState.setY(ns.getHeight() / 2); - MouseInput.getInstance().setState(mouseState, false); - } - } catch (Exception e) { - e.printStackTrace(); - } catch (UnsatisfiedLinkError e) { - e.printStackTrace(); - } + NativeScreen ns = platform.getScreen(); + Screen screen = new Screen(1l, // dummy native pointer; + ns.getDepth(), + 0, 0, ns.getWidth(), ns.getHeight(), + 0, 0, ns.getWidth(), ns.getHeight(), + 0, 0, ns.getWidth(), ns.getHeight(), + ns.getDPI(), ns.getDPI(), + ns.getScale(), ns.getScale(), + ns.getScale(), ns.getScale()); + // Move the cursor to the middle of the screen + MouseState mouseState = new MouseState(); + mouseState.setX(ns.getWidth() / 2); + mouseState.setY(ns.getHeight() / 2); + MouseInput.getInstance().setState(mouseState, false); return new Screen[] { screen }; } --- old/modules/graphics/src/main/java/com/sun/glass/ui/monocle/MonoclePixels.java 2016-03-30 23:38:51.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/monocle/MonoclePixels.java 2016-03-30 23:38:51.000000000 -0700 @@ -41,8 +41,8 @@ super(width, height, data); } - MonoclePixels(int width, int height, IntBuffer data, float scale) { - super(width, height, data, scale); + MonoclePixels(int width, int height, IntBuffer data, float scalex, float scaley) { + super(width, height, data, scalex, scaley); } --- old/modules/graphics/src/main/java/com/sun/glass/ui/win/WinApplication.java 2016-03-30 23:38:52.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/win/WinApplication.java 2016-03-30 23:38:52.000000000 -0700 @@ -38,9 +38,6 @@ final class WinApplication extends Application implements InvokeLaterDispatcher.InvokeLaterSubmitter { static float overrideUIScale; - static float overrideRenderScale; - static float minDPIScale; - static boolean forceIntegerRenderScale; private static boolean getBoolean(String propname, boolean defval, String description) { String str = System.getProperty(propname); @@ -80,10 +77,7 @@ return val; } - private static native void initIDs(float overrideUIScale, - float overrideRenderScale, - float minDPIScale, - boolean forceIntegerRenderScale); + private static native void initIDs(float overrideUIScale); static { // This loading of msvcr120.dll and msvcp120.dll (VS2013) is required when run with Java 8 // since it was build with VS2010 and doesn't include msvcr120.dll in its JRE. @@ -93,13 +87,17 @@ verbose = Boolean.getBoolean("javafx.verbose"); if (PrismSettings.allowHiDPIScaling) { overrideUIScale = getFloat("glass.win.uiScale", -1.0f, "Forcing UI scaling factor: "); - overrideRenderScale = getFloat("glass.win.renderScale", -1.0f, "Forcing Rendering scaling factor: "); - minDPIScale = getFloat("glass.win.minHiDPI", 1.5f, "Threshold to enable UI scaling factor: "); - forceIntegerRenderScale = getBoolean("glass.win.forceIntegerRenderScale", true, "forcing integer rendering scale"); + // We only parse these if verbose, to inform the user... + if (PrismSettings.verbose) { + getFloat("glass.win.renderScale", -1.0f, + "(No longer supported) Rendering scaling factor: "); + getFloat("glass.win.minHiDPI", 1.5f, + "(No longer supported) UI scaling threshold: "); + getBoolean("glass.win.forceIntegerRenderScale", true, + "(No longer supported) force integer rendering scale"); + } } else { - overrideUIScale = overrideRenderScale = 1.0f; - minDPIScale = Float.MAX_VALUE; - forceIntegerRenderScale = false; + overrideUIScale = 1.0f; } try { NativeLibLoader.loadLibrary("msvcr120"); @@ -119,7 +117,7 @@ return null; } }); - initIDs(overrideUIScale, overrideRenderScale, minDPIScale, forceIntegerRenderScale); + initIDs(overrideUIScale); } private final InvokeLaterDispatcher invokeLaterDispatcher; @@ -269,8 +267,8 @@ } @Override - public Pixels createPixels(int width, int height, IntBuffer data, float scale) { - return new WinPixels(width, height, data, scale); + public Pixels createPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + return new WinPixels(width, height, data, scalex, scaley); } @Override protected int staticPixels_getNativeFormat() { --- old/modules/graphics/src/main/java/com/sun/glass/ui/win/WinPixels.java 2016-03-30 23:38:54.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/win/WinPixels.java 2016-03-30 23:38:53.000000000 -0700 @@ -50,8 +50,8 @@ super(width, height, data); } - protected WinPixels(int width, int height, IntBuffer data, float scale) { - super(width, height, data, scale); + protected WinPixels(int width, int height, IntBuffer data, float scalex, float scaley) { + super(width, height, data, scalex, scaley); } static int getNativeFormat_impl() { --- old/modules/graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java 2016-03-30 23:38:55.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/win/WinWindow.java 2016-03-30 23:38:55.000000000 -0700 @@ -42,19 +42,10 @@ protected WinWindow(Window owner, Screen screen, int styleMask) { super(owner, screen, styleMask); - setPlatformScale(screen.getUIScale()); - setRenderScale(screen.getRenderScale()); } protected WinWindow(long parent) { super(parent); - setPlatformScale(getScreen().getUIScale()); - setRenderScale(getScreen().getRenderScale()); - } - - protected void notifyScaleChanged(float newUIScale, float newRenderScale) { - setPlatformScale(newUIScale); - setRenderScale(newRenderScale); } @Override native protected long _createWindow(long ownerPtr, long screenPtr, int mask); --- old/modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java 2016-03-30 23:38:56.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/embed/EmbeddedSceneInterface.java 2016-03-30 23:38:56.000000000 -0700 @@ -52,7 +52,7 @@ /* * A notification about the scale factor is changed. */ - public void setPixelScaleFactor(float scale); + public void setPixelScaleFactors(float scalex, float scaley); /* * A request to fetch all the FX scene pixels into a offscreen buffer. --- old/modules/graphics/src/main/java/com/sun/javafx/font/PrismFontFactory.java 2016-03-30 23:38:57.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/font/PrismFontFactory.java 2016-03-30 23:38:57.000000000 -0700 @@ -1899,7 +1899,7 @@ } static native int getLCDContrastWin32(); - private static native int getSystemFontSizeNative(); + private static native float getSystemFontSizeNative(); private static native String getSystemFontNative(); private static float systemFontSize; private static String systemFontFamily = null; @@ -1908,8 +1908,7 @@ public static float getSystemFontSize() { if (systemFontSize == -1) { if (isWindows) { - float uiScale = Screen.getMainScreen().getUIScale(); - systemFontSize = getSystemFontSizeNative() / uiScale; + systemFontSize = getSystemFontSizeNative(); } else if (isMacOSX || isIOS) { systemFontSize = MacFontFinder.getSystemFontSize(); } else if (isAndroid) { --- old/modules/graphics/src/main/java/com/sun/javafx/sg/prism/CacheFilter.java 2016-03-30 23:38:59.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/sg/prism/CacheFilter.java 2016-03-30 23:38:59.000000000 -0700 @@ -211,7 +211,9 @@ * Assumes that caller locked and validated the cachedImageData.untximage * if not null... */ - private boolean needToRenderCache(BaseTransform renderXform, double[] xformInfo, float pixelScale) { + private boolean needToRenderCache(BaseTransform renderXform, double[] xformInfo, + float pixelScaleX, float pixelScaleY) + { if (cachedImageData == null) { return true; } @@ -250,7 +252,7 @@ double scaleY = xformInfo[1]; double rotate = xformInfo[2]; if (scaleHint) { - if (cachedScaleX < pixelScale || cachedScaleY < pixelScale) { + if (cachedScaleX < pixelScaleX || cachedScaleY < pixelScaleY) { // We have moved onto a screen with a higher pixelScale and // our cache was less than that pixel scale. Even though // we have the scaleHint, we always cache at a minimum of @@ -532,8 +534,9 @@ } } } - float pixelScale = g.getAssociatedScreen().getRenderScale(); - if (needToRenderCache(xform, xformInfo, pixelScale)) { + float pixelScaleX = g.getPixelScaleFactorX(); + float pixelScaleY = g.getPixelScaleFactorY(); + if (needToRenderCache(xform, xformInfo, pixelScaleX, pixelScaleY)) { if (PulseLogger.PULSE_LOGGING_ENABLED) { PulseLogger.incrementCounter("CacheFilter rebuilding"); } @@ -548,8 +551,8 @@ // do not cache the image at a small scale factor when // scaleHint is set as it leads to poor rendering results // when image is scaled up. - cachedScaleX = Math.max(pixelScale, xformInfo[0]); - cachedScaleY = Math.max(pixelScale, xformInfo[1]); + cachedScaleX = Math.max(pixelScaleX, xformInfo[0]); + cachedScaleY = Math.max(pixelScaleY, xformInfo[1]); cachedRotate = 0; cachedXform.setTransform(cachedScaleX, 0.0, 0.0, cachedScaleX, --- old/modules/graphics/src/main/java/com/sun/javafx/sg/prism/NGCanvas.java 2016-03-30 23:39:00.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/sg/prism/NGCanvas.java 2016-03-30 23:39:00.000000000 -0700 @@ -25,7 +25,6 @@ package com.sun.javafx.sg.prism; -import com.sun.glass.ui.Screen; import javafx.geometry.VPos; import javafx.scene.text.Font; import java.nio.IntBuffer; @@ -355,9 +354,10 @@ ScreenConfigurationAccessor screenAccessor = tk.getScreenConfigurationAccessor(); float hPS = 1.0f; for (Object screen : tk.getScreens()) { - hPS = Math.max(screenAccessor.getRenderScale(screen), hPS); + hPS = Math.max(screenAccessor.getRecommendedOutputScaleX(screen), hPS); + hPS = Math.max(screenAccessor.getRecommendedOutputScaleY(screen), hPS); } - highestPixelScale = hPS; + highestPixelScale = (float) Math.ceil(hPS); cv = new RenderBuf(InitType.PRESERVE_UPPER_LEFT); temp = new RenderBuf(InitType.CLEAR); --- old/modules/graphics/src/main/java/com/sun/javafx/stage/WindowHelper.java 2016-03-30 23:39:01.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/stage/WindowHelper.java 2016-03-30 23:39:01.000000000 -0700 @@ -56,6 +56,12 @@ windowAccessor.notifySizeChanged(window, width, height); } + public static void notifyScaleChanged(final Window window, + final double newOutputScaleX, + final double newOutputScaleY) { + windowAccessor.notifyScaleChanged(window, newOutputScaleX, newOutputScaleY); + } + static AccessControlContext getAccessControlContext(Window window) { return windowAccessor.getAccessControlContext(window); } @@ -79,8 +85,10 @@ void notifyScreenChanged(Window window, Object from, Object to); - float getUIScale(Window window); - float getRenderScale(Window window); + float getPlatformScaleX(Window window); + float getPlatformScaleY(Window window); + + void notifyScaleChanged(Window window, double newOutputScaleX, double newOutputScaleY); ReadOnlyObjectProperty screenProperty(Window window); --- old/modules/graphics/src/main/java/com/sun/javafx/stage/WindowPeerListener.java 2016-03-30 23:39:03.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/stage/WindowPeerListener.java 2016-03-30 23:39:02.000000000 -0700 @@ -54,6 +54,11 @@ WindowHelper.notifySizeChanged(window, width, height); } + @Override + public void changedScale(float xScale, float yScale) { + WindowHelper.notifyScaleChanged(window, xScale, yScale); + } + public void changedFocused(boolean focused, FocusCause cause) { // Also overridden in subclasses window.setFocused(focused); --- old/modules/graphics/src/main/java/com/sun/javafx/tk/AppletWindow.java 2016-03-30 23:39:04.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/AppletWindow.java 2016-03-30 23:39:04.000000000 -0700 @@ -56,7 +56,8 @@ public int getPositionX(); public int getPositionY(); - public float getUIScale(); + public float getPlatformScaleX(); + public float getPlatformScaleY(); // returns CARemoteLayer id (only used on Mac) public int getRemoteLayerId(); --- old/modules/graphics/src/main/java/com/sun/javafx/tk/ScreenConfigurationAccessor.java 2016-03-30 23:39:05.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/ScreenConfigurationAccessor.java 2016-03-30 23:39:05.000000000 -0700 @@ -37,6 +37,6 @@ public int getVisualHeight(Object obj); public int getVisualWidth(Object obj); public float getDPI(Object obj); - public float getUIScale(Object obj); - public float getRenderScale(Object obj); + public float getRecommendedOutputScaleX(Object obj); + public float getRecommendedOutputScaleY(Object obj); } --- old/modules/graphics/src/main/java/com/sun/javafx/tk/TKStage.java 2016-03-30 23:39:07.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/TKStage.java 2016-03-30 23:39:06.000000000 -0700 @@ -81,13 +81,18 @@ * @param ch the new window content height, ignored if set to -1 * @param xGravity the xGravity coefficient * @param yGravity the yGravity coefficient + * @param renderScaleX new rendering scale, ignored if < 1 + * @param renderScaleY new rendering scale, ignored if < 1 */ public void setBounds(float x, float y, boolean xSet, boolean ySet, float w, float h, float cw, float ch, - float xGravity, float yGravity); + float xGravity, float yGravity, + float renderScaleX, float renderScaleY); - public float getUIScale(); - public float getRenderScale(); + public float getPlatformScaleX(); + public float getPlatformScaleY(); + public float getOutputScaleX(); + public float getOutputScaleY(); public void setIcons(java.util.List icons); --- old/modules/graphics/src/main/java/com/sun/javafx/tk/TKStageListener.java 2016-03-30 23:39:08.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/TKStageListener.java 2016-03-30 23:39:07.000000000 -0700 @@ -48,6 +48,14 @@ public void changedSize(float width, float height); /** + * The stage's peer should now be displayed with a new UI scale + * + * @param xScale the new recommended horizontal scale + * @param yScale the new recommended vertical scale + */ + public void changedScale(float xScale, float yScale); + + /** * The stages peer focused state has changed. * * @param focused True if the stage's peer now contains the focus --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java 2016-03-30 23:39:09.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedScene.java 2016-03-30 23:39:09.000000000 -0700 @@ -60,13 +60,15 @@ private UploadingPainter painter; private PaintRenderJob paintRenderJob; - private float renderScale; + private float renderScaleX; + private float renderScaleY; private final EmbeddedSceneDnD embeddedDnD; private volatile IntBuffer texBits; private volatile int texLineStride; // pre-scaled - private volatile float texScaleFactor = 1.0f; + private volatile float texScaleFactorX = 1.0f; + private volatile float texScaleFactorY = 1.0f; private volatile PixelFormat pixelFormat; @@ -149,15 +151,21 @@ } @Override - public void setPixelScaleFactor(float scale) { - renderScale = scale; + public void setPixelScaleFactors(float scalex, float scaley) { + renderScaleX = scalex; + renderScaleY = scaley; entireSceneNeedsRepaint(); } - public float getRenderScale() { - return renderScale; + public float getRenderScaleX() { + return renderScaleX; } + public float getRenderScaleY() { + return renderScaleY; + } + + @Override public PixelFormat getPixelFormat() { return pixelFormat; } @@ -166,7 +174,8 @@ void uploadPixels(Pixels pixels) { texBits = (IntBuffer)pixels.getPixels(); texLineStride = pixels.getWidthUnsafe(); - texScaleFactor = pixels.getScaleUnsafe(); + texScaleFactorX = pixels.getScaleXUnsafe(); + texScaleFactorY = pixels.getScaleYUnsafe(); if (host != null) { host.repaint(); } @@ -216,11 +225,14 @@ int scaledHeight = height; // The dest buffer scale factor is expected to match painter.getPixelScaleFactor(). - if (getRenderScale() != texScaleFactor || texBits == null) { + if (getRenderScaleX() != texScaleFactorX || + getRenderScaleY() != texScaleFactorY || + texBits == null) + { return false; } - scaledWidth = (int)Math.round(scaledWidth * texScaleFactor); - scaledHeight = (int)Math.round(scaledHeight * texScaleFactor); + scaledWidth = Math.round(scaledWidth * texScaleFactorX); + scaledHeight = Math.round(scaledHeight * texScaleFactorY); dest.rewind(); texBits.rewind(); --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedStage.java 2016-03-30 23:39:10.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedStage.java 2016-03-30 23:39:10.000000000 -0700 @@ -65,7 +65,8 @@ @Override public void setBounds(float x, float y, boolean xSet, boolean ySet, float w, float h, float cw, float ch, - float xGravity, float yGravity) + float xGravity, float yGravity, + float renderScaleX, float renderScaleY) { if (QuantumToolkit.verbose) { System.err.println("EmbeddedStage.setBounds: x=" + x + " y=" + y + " xSet=" + xSet + " ySet=" + ySet + @@ -76,18 +77,41 @@ if ((newW > 0) && (newH > 0)) { host.setPreferredSize((int)newW, (int)newH); } + TKScene scene = getScene(); + if ((renderScaleX > 0 || renderScaleY > 0) + && scene instanceof EmbeddedScene) + { + EmbeddedScene escene = (EmbeddedScene) scene; + if (renderScaleX <= 0.0) renderScaleX = escene.getRenderScaleX(); + if (renderScaleY <= 0.0) renderScaleY = escene.getRenderScaleY(); + escene.setPixelScaleFactors(renderScaleX, renderScaleY); + } } @Override - public float getUIScale() { + public float getPlatformScaleX() { + return 1.0f; + } + + @Override + public float getPlatformScaleY() { + return 1.0f; + } + + @Override + public float getOutputScaleX() { + TKScene scene = getScene(); + if (scene instanceof EmbeddedScene) { + return ((EmbeddedScene) scene).getRenderScaleX(); + } return 1.0f; } @Override - public float getRenderScale() { + public float getOutputScaleY() { TKScene scene = getScene(); if (scene instanceof EmbeddedScene) { - return ((EmbeddedScene) scene).getRenderScale(); + return ((EmbeddedScene) scene).getRenderScaleY(); } return 1.0f; } --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedState.java 2016-03-30 23:39:11.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/EmbeddedState.java 2016-03-30 23:39:11.000000000 -0700 @@ -82,8 +82,9 @@ @Override public void update() { super.update(); - float scale = ((EmbeddedScene) scene).getRenderScale(); - update(1.0f, scale, scale); + float scalex = ((EmbeddedScene) scene).getRenderScaleX(); + float scaley = ((EmbeddedScene) scene).getRenderScaleY(); + update(1.0f, 1.0f, scalex, scaley, scalex, scaley); if (scene != null) { // These variables and others from the super class need be kept up to date to // minimize rendering. For now, claim that the embedded scene is always visible --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java 2016-03-30 23:39:12.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassAppletWindow.java 2016-03-30 23:39:12.000000000 -0700 @@ -122,10 +122,17 @@ } @Override - public float getUIScale() { - final AtomicReference uiScale = new AtomicReference(0.0f); - Application.invokeAndWait(() -> uiScale.set(glassWindow.getPlatformScale())); - return uiScale.get(); + public float getPlatformScaleX() { + final AtomicReference pScale = new AtomicReference(0.0f); + Application.invokeAndWait(() -> pScale.set(glassWindow.getPlatformScaleX())); + return pScale.get(); + } + + @Override + public float getPlatformScaleY() { + final AtomicReference pScale = new AtomicReference(0.0f); + Application.invokeAndWait(() -> pScale.set(glassWindow.getPlatformScaleY())); + return pScale.get(); } void dispose() { --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassSceneDnDEventHandler.java 2016-03-30 23:39:13.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassSceneDnDEventHandler.java 2016-03-30 23:39:13.000000000 -0700 @@ -46,12 +46,23 @@ // Drop target handlers - private double getPlatformScale() { + private double getPlatformScaleX() { View view = scene.getPlatformView(); if (view != null) { Window w = view.getWindow(); if (w != null) { - return w.getPlatformScale(); + return w.getPlatformScaleX(); + } + } + return 1.0; + } + + private double getPlatformScaleY() { + View view = scene.getPlatformView(); + if (view != null) { + Window w = view.getWindow(); + if (w != null) { + return w.getPlatformScaleY(); } } return 1.0; @@ -64,10 +75,11 @@ assert Platform.isFxApplicationThread(); return AccessController.doPrivileged((PrivilegedAction) () -> { if (scene.dropTargetListener != null) { - double pScale = getPlatformScale(); + double pScaleX = getPlatformScaleX(); + double pScaleY = getPlatformScaleY(); QuantumClipboard dragboard = QuantumClipboard.getDragboardInstance(dropTargetAssistant, false); - return scene.dropTargetListener.dragEnter(x / pScale, y / pScale, xAbs / pScale, yAbs / pScale, + return scene.dropTargetListener.dragEnter(x / pScaleX, y / pScaleY, xAbs / pScaleX, yAbs / pScaleY, recommendedTransferMode, dragboard); } return null; @@ -91,8 +103,9 @@ assert Platform.isFxApplicationThread(); return AccessController.doPrivileged((PrivilegedAction) () -> { if (scene.dropTargetListener != null) { - double pScale = getPlatformScale(); - return scene.dropTargetListener.drop(x / pScale, y / pScale, xAbs / pScale, yAbs / pScale, + double pScaleX = getPlatformScaleX(); + double pScaleY = getPlatformScaleY(); + return scene.dropTargetListener.drop(x / pScaleX, y / pScaleY, xAbs / pScaleX, yAbs / pScaleY, recommendedTransferMode); } return null; @@ -106,8 +119,9 @@ assert Platform.isFxApplicationThread(); return AccessController.doPrivileged((PrivilegedAction) () -> { if (scene.dropTargetListener != null) { - double pScale = getPlatformScale(); - return scene.dropTargetListener.dragOver(x / pScale, y / pScale, xAbs / pScale, yAbs / pScale, + double pScaleX = getPlatformScaleX(); + double pScaleY = getPlatformScaleY(); + return scene.dropTargetListener.dragOver(x / pScaleX, y / pScaleY, xAbs / pScaleX, yAbs / pScaleY, recommendedTransferMode); } return null; @@ -126,11 +140,12 @@ assert Platform.isFxApplicationThread(); AccessController.doPrivileged((PrivilegedAction) () -> { if (scene.dragGestureListener != null) { - double pScale = getPlatformScale(); + double pScaleX = getPlatformScaleX(); + double pScaleY = getPlatformScaleY(); QuantumClipboard dragboard = QuantumClipboard.getDragboardInstance(dragSourceAssistant, true); scene.dragGestureListener.dragGestureRecognized( - x / pScale, y / pScale, xAbs / pScale, yAbs / pScale, button, dragboard); + x / pScaleX, y / pScaleY, xAbs / pScaleX, yAbs / pScaleY, button, dragboard); } return null; }, scene.getAccessControlContext()); --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java 2016-03-30 23:39:15.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassViewEventHandler.java 2016-03-30 23:39:14.000000000 -0700 @@ -346,11 +346,12 @@ boolean primaryButtonDown = (modifiers & KeyEvent.MODIFIER_BUTTON_PRIMARY) != 0; boolean middleButtonDown = (modifiers & KeyEvent.MODIFIER_BUTTON_MIDDLE) != 0; boolean secondaryButtonDown = (modifiers & KeyEvent.MODIFIER_BUTTON_SECONDARY) != 0; - Window w = view.getWindow(); - double pScale = (w == null) ? 1.0 : w.getPlatformScale(); + final Window w = view.getWindow(); + double pScaleX = (w == null) ? 1.0 : w.getPlatformScaleX(); + double pScaleY = (w == null) ? 1.0 : w.getPlatformScaleY(); scene.sceneListener.mouseEvent(mouseEventType(type), - x / pScale, y / pScale, xAbs / pScale, yAbs / pScale, + x / pScaleX, y / pScaleY, xAbs / pScaleX, yAbs / pScaleY, mouseEventButton(button), isPopupTrigger, isSynthesized, shiftDown, controlDown, altDown, metaDown, primaryButtonDown, middleButtonDown, secondaryButtonDown); @@ -404,10 +405,11 @@ QuantumToolkit.runWithoutRenderLock(() -> { return AccessController.doPrivileged((PrivilegedAction) () -> { if (scene.sceneListener != null) { - Window w = view.getWindow(); - double pScale = (w == null) ? 1.0 : w.getPlatformScale(); - scene.sceneListener.menuEvent(x / pScale, y / pScale, - xAbs / pScale, yAbs / pScale, + final Window w = view.getWindow(); + double pScaleX = (w == null) ? 1.0 : w.getPlatformScaleX(); + double pScaleY = (w == null) ? 1.0 : w.getPlatformScaleY(); + scene.sceneListener.menuEvent(x / pScaleX, y / pScaleY, + xAbs / pScaleX, yAbs / pScaleY, isKeyboardTrigger); } return null; @@ -441,14 +443,15 @@ QuantumToolkit.runWithoutRenderLock(() -> { return AccessController.doPrivileged((PrivilegedAction) () -> { if (scene.sceneListener != null) { - Window w = view.getWindow(); - double pScale = (w == null) ? 1.0 : w.getPlatformScale(); + final Window w = view.getWindow(); + double pScaleX = (w == null) ? 1.0 : w.getPlatformScaleX(); + double pScaleY = (w == null) ? 1.0 : w.getPlatformScaleY(); scene.sceneListener.scrollEvent(ScrollEvent.SCROLL, - deltaX / pScale, deltaY / pScale, 0, 0, + deltaX / pScaleX, deltaY / pScaleY, 0, 0, xMultiplier, yMultiplier, 0, // touchCount chars, lines, defaultChars, defaultLines, - x / pScale, y / pScale, xAbs / pScale, yAbs / pScale, + x / pScaleX, y / pScaleY, xAbs / pScaleX, yAbs / pScaleY, (modifiers & KeyEvent.MODIFIER_SHIFT) != 0, (modifiers & KeyEvent.MODIFIER_CONTROL) != 0, (modifiers & KeyEvent.MODIFIER_ALT) != 0, @@ -773,10 +776,11 @@ break; } case ViewEvent.RESIZE: { - Window w = view.getWindow(); - float pScale = (w == null) ? 1.0f : w.getPlatformScale(); - scene.sceneListener.changedSize(view.getWidth() / pScale, - view.getHeight() / pScale); + final Window w = view.getWindow(); + float pScaleX = (w == null) ? 1.0f : w.getPlatformScaleX(); + float pScaleY = (w == null) ? 1.0f : w.getPlatformScaleY(); + scene.sceneListener.changedSize(view.getWidth() / pScaleX, + view.getHeight() / pScaleY); scene.entireSceneNeedsRepaint(); QuantumToolkit.runWithRenderLock(() -> { scene.updateSceneState(); @@ -793,10 +797,11 @@ case ViewEvent.MOVE: { // MOVE events can be "synthesized" and the window will // be null if this is synthesized during a "REMOVE" event - Window w = view.getWindow(); - float pScale = (w == null) ? 1.0f : w.getPlatformScale(); - scene.sceneListener.changedLocation(view.getX() / pScale, - view.getY() / pScale); + final Window w = view.getWindow(); + float pScaleX = (w == null) ? 1.0f : w.getPlatformScaleX(); + float pScaleY = (w == null) ? 1.0f : w.getPlatformScaleY(); + scene.sceneListener.changedLocation(view.getX() / pScaleX, + view.getY() / pScaleY); break; } case ViewEvent.FULLSCREEN_ENTER: @@ -866,17 +871,18 @@ default: throw new RuntimeException("Unknown scroll event type: " + type); } - Window w = view.getWindow(); - double pScale = (w == null) ? 1.0 : w.getPlatformScale(); + final Window w = view.getWindow(); + double pScaleX = (w == null) ? 1.0 : w.getPlatformScaleX(); + double pScaleY = (w == null) ? 1.0 : w.getPlatformScaleY(); scene.sceneListener.scrollEvent(eventType, - dx / pScale, dy / pScale, totaldx / pScale, totaldy / pScale, + dx / pScaleX, dy / pScaleY, totaldx / pScaleX, totaldy / pScaleY, multiplierX, multiplierY, touchCount, 0, 0, 0, 0, - x == View.GESTURE_NO_VALUE ? Double.NaN : x / pScale, - y == View.GESTURE_NO_VALUE ? Double.NaN : y / pScale, - xAbs == View.GESTURE_NO_VALUE ? Double.NaN : xAbs / pScale, - yAbs == View.GESTURE_NO_VALUE ? Double.NaN : yAbs / pScale, + x == View.GESTURE_NO_VALUE ? Double.NaN : x / pScaleX, + y == View.GESTURE_NO_VALUE ? Double.NaN : y / pScaleY, + xAbs == View.GESTURE_NO_VALUE ? Double.NaN : xAbs / pScaleX, + yAbs == View.GESTURE_NO_VALUE ? Double.NaN : yAbs / pScaleY, (modifiers & KeyEvent.MODIFIER_SHIFT) != 0, (modifiers & KeyEvent.MODIFIER_CONTROL) != 0, (modifiers & KeyEvent.MODIFIER_ALT) != 0, @@ -929,14 +935,15 @@ default: throw new RuntimeException("Unknown scroll event type: " + type); } - Window w = view.getWindow(); - double pScale = (w == null) ? 1.0 : w.getPlatformScale(); + final Window w = view.getWindow(); + double pScaleX = (w == null) ? 1.0 : w.getPlatformScaleX(); + double pScaleY = (w == null) ? 1.0 : w.getPlatformScaleY(); // REMIND: Scale the [total]scale params too? scene.sceneListener.zoomEvent(eventType, scale, totalscale, - originx == View.GESTURE_NO_VALUE ? Double.NaN : originx / pScale, - originy == View.GESTURE_NO_VALUE ? Double.NaN : originy / pScale, - originxAbs == View.GESTURE_NO_VALUE ? Double.NaN : originxAbs / pScale, - originyAbs == View.GESTURE_NO_VALUE ? Double.NaN : originyAbs / pScale, + originx == View.GESTURE_NO_VALUE ? Double.NaN : originx / pScaleX, + originy == View.GESTURE_NO_VALUE ? Double.NaN : originy / pScaleY, + originxAbs == View.GESTURE_NO_VALUE ? Double.NaN : originxAbs / pScaleX, + originyAbs == View.GESTURE_NO_VALUE ? Double.NaN : originyAbs / pScaleY, (modifiers & KeyEvent.MODIFIER_SHIFT) != 0, (modifiers & KeyEvent.MODIFIER_CONTROL) != 0, (modifiers & KeyEvent.MODIFIER_ALT) != 0, @@ -988,13 +995,14 @@ default: throw new RuntimeException("Unknown scroll event type: " + type); } - Window w = view.getWindow(); - double pScale = (w == null) ? 1.0 : w.getPlatformScale(); + final Window w = view.getWindow(); + double pScaleX = (w == null) ? 1.0 : w.getPlatformScaleX(); + double pScaleY = (w == null) ? 1.0 : w.getPlatformScaleY(); scene.sceneListener.rotateEvent(eventType, dangle, totalangle, - originx == View.GESTURE_NO_VALUE ? Double.NaN : originx / pScale, - originy == View.GESTURE_NO_VALUE ? Double.NaN : originy / pScale, - originxAbs == View.GESTURE_NO_VALUE ? Double.NaN : originxAbs / pScale, - originyAbs == View.GESTURE_NO_VALUE ? Double.NaN : originyAbs / pScale, + originx == View.GESTURE_NO_VALUE ? Double.NaN : originx / pScaleX, + originy == View.GESTURE_NO_VALUE ? Double.NaN : originy / pScaleY, + originxAbs == View.GESTURE_NO_VALUE ? Double.NaN : originxAbs / pScaleX, + originyAbs == View.GESTURE_NO_VALUE ? Double.NaN : originyAbs / pScaleY, (modifiers & KeyEvent.MODIFIER_SHIFT) != 0, (modifiers & KeyEvent.MODIFIER_CONTROL) != 0, (modifiers & KeyEvent.MODIFIER_ALT) != 0, @@ -1048,13 +1056,14 @@ default: throw new RuntimeException("Unknown swipe event direction: " + dir); } - Window w = view.getWindow(); - double pScale = (w == null) ? 1.0 : w.getPlatformScale(); + final Window w = view.getWindow(); + double pScaleX = (w == null) ? 1.0 : w.getPlatformScaleX(); + double pScaleY = (w == null) ? 1.0 : w.getPlatformScaleY(); scene.sceneListener.swipeEvent(eventType, touchCount, - x == View.GESTURE_NO_VALUE ? Double.NaN : x / pScale, - y == View.GESTURE_NO_VALUE ? Double.NaN : y / pScale, - xAbs == View.GESTURE_NO_VALUE ? Double.NaN : xAbs / pScale, - yAbs == View.GESTURE_NO_VALUE ? Double.NaN : yAbs / pScale, + x == View.GESTURE_NO_VALUE ? Double.NaN : x / pScaleX, + y == View.GESTURE_NO_VALUE ? Double.NaN : y / pScaleY, + xAbs == View.GESTURE_NO_VALUE ? Double.NaN : xAbs / pScaleX, + yAbs == View.GESTURE_NO_VALUE ? Double.NaN : yAbs / pScaleY, (modifiers & KeyEvent.MODIFIER_SHIFT) != 0, (modifiers & KeyEvent.MODIFIER_CONTROL) != 0, (modifiers & KeyEvent.MODIFIER_ALT) != 0, @@ -1143,10 +1152,11 @@ default: throw new RuntimeException("Unknown touch state: " + type); } - Window w = view.getWindow(); - double pScale = (w == null) ? 1.0 : w.getPlatformScale(); + final Window w = view.getWindow(); + double pScaleX = (w == null) ? 1.0 : w.getPlatformScaleX(); + double pScaleY = (w == null) ? 1.0 : w.getPlatformScaleY(); scene.sceneListener.touchEventNext(state, touchId, - x / pScale, y / pScale, xAbs / pScale, yAbs / pScale); + x / pScaleX, y / pScaleY, xAbs / pScaleX, yAbs / pScaleY); } return null; }, scene.getAccessControlContext()); --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassWindowEventHandler.java 2016-03-30 23:39:16.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/GlassWindowEventHandler.java 2016-03-30 23:39:16.000000000 -0700 @@ -65,14 +65,23 @@ stage.stageListener.changedMaximized(false); break; case WindowEvent.MOVE: { - float pScale = window.getPlatformScale(); - Screen screen = window.getScreen(); - float sx = screen == null ? 0 : screen.getX(); - float sy = screen == null ? 0 : screen.getY(); float wx = window.getX(); float wy = window.getY(); - float newx = sx + (wx - sx) / pScale; - float newy = sy + (wy - sy) / pScale; + Screen screen = window.getScreen(); + float newx, newy; + if (screen != null) { + float pScaleX = screen.getPlatformScaleX(); + float pScaleY = screen.getPlatformScaleY(); + float sx = screen.getX(); + float sy = screen.getY(); + float px = screen.getPlatformX(); + float py = screen.getPlatformY(); + newx = sx + (wx - px) / pScaleX; + newy = sy + (wy - py) / pScaleY; + } else { + newx = wx; + newy = wy; + } stage.stageListener.changedLocation(newx, newy); //We need to sync the new x,y for painting if (!Application.GetApplication().hasWindowManager()) { @@ -87,11 +96,27 @@ break; } case WindowEvent.RESIZE: { - float pScale = window.getPlatformScale(); - stage.stageListener.changedSize(window.getWidth() / pScale, - window.getHeight() / pScale); + float pScaleX = window.getPlatformScaleX(); + float pScaleY = window.getPlatformScaleY(); + stage.stageListener.changedSize(window.getWidth() / pScaleX, + window.getHeight() / pScaleY); break; } + case WindowEvent.RESCALE: { + float outScaleX = window.getOutputScaleX(); + float outScaleY = window.getOutputScaleY(); + stage.stageListener.changedScale(outScaleX, outScaleY); + // We need to sync the new scales for painting + QuantumToolkit.runWithRenderLock(() -> { + GlassScene scene = stage.getScene(); + if (scene != null) { + scene.entireSceneNeedsRepaint(); + scene.updateSceneState(); + } + return null; + }); + break; + } case WindowEvent.FOCUS_GAINED: WindowStage.addActiveWindow(stage); stage.stageListener.changedFocused(true, FocusCause.ACTIVATED); --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java 2016-03-30 23:39:17.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/QuantumToolkit.java 2016-03-30 23:39:17.000000000 -0700 @@ -653,11 +653,11 @@ @Override public float getDPI(Object obj) { return ((Screen)obj).getResolutionX(); } - @Override public float getUIScale(Object obj) { - return ((Screen)obj).getUIScale(); + @Override public float getRecommendedOutputScaleX(Object obj) { + return ((Screen)obj).getRecommendedOutputScaleX(); } - @Override public float getRenderScale(Object obj) { - return ((Screen)obj).getRenderScale(); + @Override public float getRecommendedOutputScaleY(Object obj) { + return ((Screen)obj).getRecommendedOutputScaleY(); } }; @@ -706,10 +706,18 @@ return new PerformanceTrackerImpl(); } - public float getMaxRenderScale() { + // Only currently called from the loadImage method below. We do not + // necessarily know what the worst render scale we will ever see is + // because the user has control over that, but we should be loading + // all dpi variants of an image at all times anyway and then using + // whichever one is needed to respond to a given rendering request + // rather than predetermining which one to use up front. If we switch + // to making that decision at render time then this method can go away. + private float getMaxRenderScale() { if (_maxPixelScale == 0) { for (Object o : getScreens()) { - _maxPixelScale = Math.max(_maxPixelScale, ((Screen) o).getRenderScale()); + _maxPixelScale = Math.max(_maxPixelScale, ((Screen) o).getRecommendedOutputScaleX()); + _maxPixelScale = Math.max(_maxPixelScale, ((Screen) o).getRecommendedOutputScaleY()); } } return _maxPixelScale; --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/UploadingPainter.java 2016-03-30 23:39:18.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/UploadingPainter.java 2016-03-30 23:39:18.000000000 -0700 @@ -46,7 +46,7 @@ private RTTexture resolveRTT = null; private QueuedPixelSource pixelSource = new QueuedPixelSource(true); - private float penScale; + private float penScaleX, penScaleY; UploadingPainter(GlassScene view) { super(view); @@ -64,8 +64,13 @@ } @Override - public float getPixelScaleFactor() { - return sceneState.getRenderScale(); + public float getPixelScaleFactorX() { + return sceneState.getRenderScaleX(); + } + + @Override + public float getPixelScaleFactorY() { + return sceneState.getRenderScaleY(); } @Override public void run() { @@ -88,7 +93,8 @@ return; } - float scale = getPixelScaleFactor(); + float scalex = getPixelScaleFactorX(); + float scaley = getPixelScaleFactorY(); int bufWidth = sceneState.getRenderWidth(); int bufHeight = sceneState.getRenderHeight(); @@ -96,7 +102,8 @@ // texture contents are no longer correct. // Repaint everything on new texture dimensions because otherwise // our upload logic below may fail with index out of bounds. - boolean needsReset = (penScale != scale || + boolean needsReset = (penScaleX != scalex || + penScaleY != scaley || penWidth != viewWidth || penHeight != viewHeight || rttexture == null || @@ -119,7 +126,8 @@ if (rttexture == null) { return; } - penScale = scale; + penScaleX = scalex; + penScaleY = scaley; penWidth = viewWidth; penHeight = viewHeight; freshBackBuffer = true; @@ -130,13 +138,14 @@ sceneState.getScene().entireSceneNeedsRepaint(); return; } - g.scale(scale, scale); + g.scale(scalex, scaley); paintImpl(g); freshBackBuffer = false; int outWidth = sceneState.getOutputWidth(); int outHeight = sceneState.getOutputHeight(); - float outScale = sceneState.getOutputScale(); + float outScaleX = sceneState.getOutputScaleX(); + float outScaleY = sceneState.getOutputScaleY(); RTTexture rtt; if (rttexture.isMSAA() || outWidth != bufWidth || outHeight != bufHeight) { rtt = resolveRenderTarget(g, outWidth, outHeight); @@ -144,7 +153,7 @@ rtt = rttexture; } - Pixels pix = pixelSource.getUnusedPixels(outWidth, outHeight, outScale); + Pixels pix = pixelSource.getUnusedPixels(outWidth, outHeight, outScaleX, outScaleY); IntBuffer bits = (IntBuffer) pix.getPixels(); int rawbits[] = rtt.getPixels(); --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/ViewPainter.java 2016-03-30 23:39:19.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/ViewPainter.java 2016-03-30 23:39:19.000000000 -0700 @@ -174,9 +174,10 @@ // might be reassigned to the sceneBuffer graphics. Graphics g = backBufferGraphics; // Take into account the pixel scale factor for retina displays - final float pixelScale = getPixelScaleFactor(); + final float pixelScaleX = getPixelScaleFactorX(); + final float pixelScaleY = getPixelScaleFactorY(); // Cache pixelScale in Graphics for use in 3D shaders such as camera and light positions. - g.setPixelScaleFactor(pixelScale); + g.setPixelScaleFactors(pixelScaleX, pixelScaleY); // Initialize renderEverything based on various conditions that will cause us to render // the entire scene every time. @@ -192,8 +193,8 @@ // then we will render the scene to an intermediate texture, and then at the end we'll // draw that intermediate texture to the back buffer. if (showDirtyOpts && !sceneState.getScene().getDepthBuffer()) { - final int bufferWidth = (int) Math.ceil(width * pixelScale); - final int bufferHeight = (int) Math.ceil(height * pixelScale); + final int bufferWidth = (int) Math.ceil(width * pixelScaleX); + final int bufferHeight = (int) Math.ceil(height * pixelScaleY); // Check whether the sceneBuffer texture needs to be reconstructed if (sceneBuffer != null) { sceneBuffer.lock(); @@ -219,7 +220,8 @@ sceneBuffer.contentsUseful(); // Hijack the "g" graphics variable g = sceneBuffer.createGraphics(); - g.scale(pixelScale, pixelScale); + g.setPixelScaleFactors(pixelScaleX, pixelScaleY); + g.scale(pixelScaleX, pixelScaleY); } else if (sceneBuffer != null) { // We're in a situation where we have previously rendered to the sceneBuffer, but in // this render pass for whatever reason we're going to draw directly to the back buffer. @@ -312,11 +314,11 @@ dirtyRect.setBounds(dirtyRegion); // TODO I don't understand why this is needed. And if it is, are fractional pixelScale // values OK? And if not, shouldn't pixelScale be an int instead? - if (pixelScale != 1.0f) { - dirtyRect.x *= pixelScale; - dirtyRect.y *= pixelScale; - dirtyRect.width *= pixelScale; - dirtyRect.height *= pixelScale; + if (pixelScaleX != 1.0f || pixelScaleY != 1.0f) { + dirtyRect.x *= pixelScaleX; + dirtyRect.y *= pixelScaleY; + dirtyRect.width *= pixelScaleX; + dirtyRect.height *= pixelScaleY; } g.setClipRect(dirtyRect); g.setClipRectIndex(i); @@ -437,8 +439,12 @@ return sceneState.isWindowVisible() && !sceneState.isWindowMinimized(); } - protected float getPixelScaleFactor() { - return presentable == null ? 1.0f : presentable.getPixelScaleFactor(); + protected float getPixelScaleFactorX() { + return presentable == null ? 1.0f : presentable.getPixelScaleFactorX(); + } + + protected float getPixelScaleFactorY() { + return presentable == null ? 1.0f : presentable.getPixelScaleFactorY(); } private void doPaint(Graphics g, NodePath renderRootPath) { --- old/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/WindowStage.java 2016-03-30 23:39:21.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/javafx/tk/quantum/WindowStage.java 2016-03-30 23:39:20.000000000 -0700 @@ -277,69 +277,130 @@ @Override public void setBounds(float x, float y, boolean xSet, boolean ySet, float w, float h, float cw, float ch, - float xGravity, float yGravity) + float xGravity, float yGravity, + float renderScaleX, float renderScaleY) { + if (renderScaleX > 0.0 || renderScaleY > 0.0) { + // We set the render scale first since the call to setBounds() + // below can induce a recursive update on the scales if it moves + // the window to a new screen and we will then end up being called + // back with a new scale. We do not want to set these old scale + // values after that recursion happens. + if (renderScaleX > 0.0) { + platformWindow.setRenderScaleX(renderScaleX); + } + if (renderScaleY > 0.0) { + platformWindow.setRenderScaleY(renderScaleY); + } + ViewScene vscene = getViewScene(); + if (vscene != null) { + vscene.updateSceneState(); + vscene.entireSceneNeedsRepaint(); + } + } if (isAppletStage) { xSet = ySet = false; } - float pScale = platformWindow.getPlatformScale(); + float pScaleX = platformWindow.getPlatformScaleX(); + float pScaleY = platformWindow.getPlatformScaleY(); int px, py; if (xSet || ySet) { Screen screen = platformWindow.getScreen(); List screens = Screen.getScreens(); if (screens.size() > 1) { - float wx = xSet ? x : platformWindow.getX(); - float wy = ySet ? y : platformWindow.getY(); - float relx = screen.getX() + screen.getWidth() / 2.0f - wx; - float rely = screen.getY() + screen.getHeight()/ 2.0f - wy; - float distsq = relx * relx + rely * rely; - for (Screen s : Screen.getScreens()) { - relx = s.getX() + s.getWidth() / 2.0f - wx; - rely = s.getY() + s.getHeight()/ 2.0f - wy; - float distsq2 = relx * relx + rely * rely; - if (distsq2 < distsq) { - screen = s; - distsq = distsq2; + float winfxW = (w > 0) ? w : (platformWindow.getWidth() / pScaleX); + float winfxH = (h > 0) ? h : (platformWindow.getHeight()/ pScaleY); + float winfxX = xSet ? x : + screen.getX() + (platformWindow.getX() - screen.getPlatformX()) / pScaleX; + float winfxY = ySet ? y : + screen.getY() + (platformWindow.getY() - screen.getPlatformY()) / pScaleY; + float winfxCX = winfxX + winfxW/2f; + float winfxCY = winfxY + winfxH/2f; + // If the center point of the window (winfxCX,Y) is on any + // screen, then use that screen. Otherwise, use the screen + // whose center is closest to the window center. + int scrX = screen.getX(); + int scrY = screen.getY(); + int scrW = screen.getWidth(); + int scrH = screen.getHeight(); + if (winfxCX < scrX || + winfxCY < scrY || + winfxCX >= scrX + scrW || + winfxCY >= scrY + scrH) + { + float relx = scrX + scrW / 2.0f - winfxCX; + float rely = scrY + scrH / 2.0f - winfxCY; + float distsq = relx * relx + rely * rely; + for (Screen s : Screen.getScreens()) { + scrX = s.getX(); + scrY = s.getY(); + scrW = s.getWidth(); + scrH = s.getHeight(); + if (winfxCX >= scrX && + winfxCY >= scrY && + winfxCX < scrX + scrW && + winfxCY < scrY + scrH) + { + screen = s; + break; + } + relx = scrX + scrW / 2.0f - winfxCX; + rely = scrY + scrH / 2.0f - winfxCY; + float distsq2 = relx * relx + rely * rely; + if (distsq2 < distsq) { + screen = s; + distsq = distsq2; + } } } } float sx = screen == null ? 0 : screen.getX(); float sy = screen == null ? 0 : screen.getY(); - px = xSet ? Math.round(sx + (x - sx) * pScale) : 0; - py = ySet ? Math.round(sy + (y - sy) * pScale) : 0; + float sScaleX = screen.getPlatformScaleX(); + float sScaleY = screen.getPlatformScaleY(); + px = xSet ? Math.round(screen.getPlatformX() + (x - sx) * sScaleX) : 0; + py = ySet ? Math.round(screen.getPlatformY() + (y - sy) * sScaleY) : 0; } else { px = py = 0; } - int pw = (int) (w > 0 ? Math.ceil(w * pScale) : w); - int ph = (int) (h > 0 ? Math.ceil(h * pScale) : h); - int pcw = (int) (cw > 0 ? Math.ceil(cw * pScale) : cw); - int pch = (int) (ch > 0 ? Math.ceil(ch * pScale) : ch); + int pw = (int) (w > 0 ? Math.ceil(w * pScaleX) : w); + int ph = (int) (h > 0 ? Math.ceil(h * pScaleY) : h); + int pcw = (int) (cw > 0 ? Math.ceil(cw * pScaleX) : cw); + int pch = (int) (ch > 0 ? Math.ceil(ch * pScaleY) : ch); platformWindow.setBounds(px, py, xSet, ySet, pw, ph, pcw, pch, xGravity, yGravity); } @Override - public float getUIScale() { - return platformWindow.getPlatformScale(); + public float getPlatformScaleX() { + return platformWindow.getPlatformScaleX(); + } + + @Override + public float getPlatformScaleY() { + return platformWindow.getPlatformScaleY(); + } + + @Override + public float getOutputScaleX() { + return platformWindow.getOutputScaleX(); } @Override - public float getRenderScale() { - return platformWindow.getRenderScale(); + public float getOutputScaleY() { + return platformWindow.getOutputScaleY(); } @Override public void setMinimumSize(int minWidth, int minHeight) { - float pScale = platformWindow.getPlatformScale(); - minWidth = (int) Math.ceil(minWidth * pScale); - minHeight = (int) Math.ceil(minHeight * pScale); + minWidth = (int) Math.ceil(minWidth * getPlatformScaleX()); + minHeight = (int) Math.ceil(minHeight * getPlatformScaleY()); platformWindow.setMinimumSize(minWidth, minHeight); } @Override public void setMaximumSize(int maxWidth, int maxHeight) { - float pScale = platformWindow.getPlatformScale(); - maxWidth = (int) Math.ceil(maxWidth * pScale); - maxHeight = (int) Math.ceil(maxHeight * pScale); + maxWidth = (int) Math.ceil(maxWidth * getPlatformScaleX()); + maxHeight = (int) Math.ceil(maxHeight * getPlatformScaleY()); platformWindow.setMaximumSize(maxWidth, maxHeight); } --- old/modules/graphics/src/main/java/com/sun/prism/Graphics.java 2016-03-30 23:39:22.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/Graphics.java 2016-03-30 23:39:22.000000000 -0700 @@ -210,6 +210,7 @@ // TODO this is dangerous, must be called *after* setState3D is called, or it won't work public void setup3DRendering(); - public void setPixelScaleFactor(float pixelScale); - public float getPixelScaleFactor(); + public void setPixelScaleFactors(float pixelScaleX, float pixelScaleY); + public float getPixelScaleFactorX(); + public float getPixelScaleFactorY(); } --- old/modules/graphics/src/main/java/com/sun/prism/Presentable.java 2016-03-30 23:39:23.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/Presentable.java 2016-03-30 23:39:23.000000000 -0700 @@ -57,5 +57,6 @@ */ public boolean present(); - public float getPixelScaleFactor(); + public float getPixelScaleFactorX(); + public float getPixelScaleFactorY(); } --- old/modules/graphics/src/main/java/com/sun/prism/PresentableState.java 2016-03-30 23:39:24.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/PresentableState.java 2016-03-30 23:39:24.000000000 -0700 @@ -50,9 +50,9 @@ protected long nativeWindowHandle; protected long nativeView; protected int viewWidth, viewHeight; - protected float renderScale; + protected float renderScaleX, renderScaleY; protected int renderWidth, renderHeight; - protected float outputScale; + protected float outputScaleX, outputScaleY; protected int outputWidth, outputHeight; protected int screenHeight; protected int screenWidth; @@ -132,12 +132,25 @@ * * May be called on any thread */ - public float getRenderScale() { - return renderScale; + public float getRenderScaleX() { + return renderScaleX; } - public float getOutputScale() { - return outputScale; + /** + * @return Screen.getScale + * + * May be called on any thread + */ + public float getRenderScaleY() { + return renderScaleY; + } + + public float getOutputScaleX() { + return outputScaleX; + } + + public float getOutputScaleY() { + return outputScaleY; } /** @@ -305,25 +318,30 @@ : (int) Math.ceil(dim * toScale / fromScale); } - protected void update(float viewScale, float renderScale, float outputScale) { - this.renderScale = renderScale; - this.outputScale = outputScale; - if (renderScale == viewScale) { + protected void update(float viewScaleX, float viewScaleY, + float renderScaleX, float renderScaleY, + float outputScaleX, float outputScaleY) + { + this.renderScaleX = renderScaleX; + this.renderScaleY = renderScaleY; + this.outputScaleX = outputScaleX; + this.outputScaleY = outputScaleY; + if (renderScaleX == viewScaleX && renderScaleY == viewScaleY) { renderWidth = viewWidth; renderHeight = viewHeight; } else { - renderWidth = scale(viewWidth, viewScale, renderScale); - renderHeight = scale(viewHeight, viewScale, renderScale); + renderWidth = scale(viewWidth, viewScaleX, renderScaleX); + renderHeight = scale(viewHeight, viewScaleY, renderScaleY); } - if (outputScale == viewScale) { + if (outputScaleX == viewScaleX && outputScaleY == viewScaleY) { outputWidth = viewWidth; outputHeight = viewHeight; - } else if (outputScale == renderScale) { + } else if (outputScaleX == renderScaleX && outputScaleY == renderScaleY) { outputWidth = renderWidth; outputHeight = renderHeight; } else { - outputWidth = scale(viewWidth, viewScale, outputScale); - outputHeight = scale(viewHeight, viewScale, outputScale); + outputWidth = scale(viewWidth, viewScaleX, outputScaleX); + outputHeight = scale(viewHeight, viewScaleY, outputScaleY); } } @@ -351,9 +369,9 @@ isClosed = view.isClosed(); isWindowVisible = window.isVisible(); isWindowMinimized = window.isMinimized(); - update(window.getPlatformScale(), - window.getRenderScale(), - window.getOutputScale()); + update(window.getPlatformScaleX(), window.getPlatformScaleY(), + window.getRenderScaleX(), window.getRenderScaleY(), + window.getOutputScaleX(), window.getOutputScaleY()); Screen screen = window.getScreen(); if (screen != null) { // note only used by Embedded Z order painting --- old/modules/graphics/src/main/java/com/sun/prism/d3d/D3DContext.java 2016-03-30 23:39:25.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/d3d/D3DContext.java 2016-03-30 23:39:25.000000000 -0700 @@ -552,9 +552,10 @@ // Support retina display by scaling the projViewTx and pass it to the shader. scratchTx = scratchTx.set(projViewTx); - float pixelScaleFactor = g.getPixelScaleFactor(); - if (pixelScaleFactor != 1.0) { - scratchTx.scale(pixelScaleFactor, pixelScaleFactor, 1.0); + float pixelScaleFactorX = g.getPixelScaleFactorX(); + float pixelScaleFactorY = g.getPixelScaleFactorY(); + if (pixelScaleFactorX != 1.0 || pixelScaleFactorY != 1.0) { + scratchTx.scale(pixelScaleFactorX, pixelScaleFactorY, 1.0); } // Set projection view matrix @@ -571,10 +572,9 @@ // Undo the SwapChain scaling done in createGraphics() because 3D needs // this information in the shader (via projViewTx) BaseTransform xform = g.getTransformNoClone(); - if (pixelScaleFactor != 1.0) { - float invPSF = 1 / pixelScaleFactor; + if (pixelScaleFactorX != 1.0 || pixelScaleFactorY != 1.0) { scratchAffine3DTx.setToIdentity(); - scratchAffine3DTx.scale(invPSF, invPSF); + scratchAffine3DTx.scale(1.0 / pixelScaleFactorX, 1.0 / pixelScaleFactorY); scratchAffine3DTx.concatenate(xform); updateWorldTransform(scratchAffine3DTx); } else { --- old/modules/graphics/src/main/java/com/sun/prism/d3d/D3DResourceFactory.java 2016-03-30 23:39:26.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/d3d/D3DResourceFactory.java 2016-03-30 23:39:26.000000000 -0700 @@ -335,7 +335,7 @@ } if (rtt != null) { - return new D3DSwapChain(context, pResource, rtt, pState.getRenderScale()); + return new D3DSwapChain(context, pResource, rtt, pState.getRenderScaleX(), pState.getRenderScaleY()); } D3DResourceFactory.nReleaseResource(context.getContextHandle(), pResource); --- old/modules/graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java 2016-03-30 23:39:27.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/d3d/D3DSwapChain.java 2016-03-30 23:39:27.000000000 -0700 @@ -38,12 +38,14 @@ implements D3DRenderTarget, Presentable, D3DContextSource { private final D3DRTTexture texBackBuffer; - private final float pixelScaleFactor; + private final float pixelScaleFactorX; + private final float pixelScaleFactorY; - D3DSwapChain(D3DContext context, long pResource, D3DRTTexture rtt, float pixelScale) { + D3DSwapChain(D3DContext context, long pResource, D3DRTTexture rtt, float pixelScaleX, float pixelScaleY) { super(new D3DRecord(context, pResource)); texBackBuffer = rtt; - pixelScaleFactor = pixelScale; + pixelScaleFactorX = pixelScaleX; + pixelScaleFactorY = pixelScaleY; } @Override @@ -119,7 +121,8 @@ public boolean lockResources(PresentableState pState) { if (pState.getRenderWidth() != texBackBuffer.getContentWidth() || pState.getRenderHeight() != texBackBuffer.getContentHeight() || - pState.getRenderScale() != pixelScaleFactor) + pState.getRenderScaleX() != pixelScaleFactorX || + pState.getRenderScaleY() != pixelScaleFactorY) { return true; } @@ -129,7 +132,7 @@ public Graphics createGraphics() { Graphics g = D3DGraphics.create(texBackBuffer, getContext()); - g.scale(pixelScaleFactor, pixelScaleFactor); + g.scale(pixelScaleFactorX, pixelScaleFactorY); return g; } @@ -141,8 +144,14 @@ return getContext().getAssociatedScreen(); } - public float getPixelScaleFactor() { - return pixelScaleFactor; + @Override + public float getPixelScaleFactorX() { + return pixelScaleFactorX; + } + + @Override + public float getPixelScaleFactorY() { + return pixelScaleFactorY; } public boolean isOpaque() { --- old/modules/graphics/src/main/java/com/sun/prism/es2/ES2Context.java 2016-03-30 23:39:29.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/es2/ES2Context.java 2016-03-30 23:39:28.000000000 -0700 @@ -467,10 +467,11 @@ setShaderProgram(shader.getProgramObject()); // Support retina display by scaling the projViewTx and pass it to the shader. - float pixelScaleFactor = g.getPixelScaleFactor(); - if (pixelScaleFactor != 1.0) { + float pixelScaleFactorX = g.getPixelScaleFactorX(); + float pixelScaleFactorY = g.getPixelScaleFactorY(); + if (pixelScaleFactorX != 1.0 || pixelScaleFactorY != 1.0) { scratchTx = scratchTx.set(projViewTx); - scratchTx.scale(pixelScaleFactor, pixelScaleFactor, 1.0); + scratchTx.scale(pixelScaleFactorX, pixelScaleFactorY, 1.0); updateRawMatrix(scratchTx); } else { updateRawMatrix(projViewTx); @@ -482,10 +483,9 @@ // Undo the SwapChain scaling done in createGraphics() because 3D needs // this information in the shader (via projViewTx) BaseTransform xform = g.getTransformNoClone(); - if (pixelScaleFactor != 1.0) { - float invPSF = 1/pixelScaleFactor; + if (pixelScaleFactorX != 1.0 || pixelScaleFactorY != 1.0) { scratchAffine3DTx.setToIdentity(); - scratchAffine3DTx.scale(invPSF, invPSF); + scratchAffine3DTx.scale(1.0 / pixelScaleFactorX, 1.0 / pixelScaleFactorY); scratchAffine3DTx.concatenate(xform); updateWorldTransform(scratchAffine3DTx); } else { --- old/modules/graphics/src/main/java/com/sun/prism/es2/ES2SwapChain.java 2016-03-30 23:39:30.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/es2/ES2SwapChain.java 2016-03-30 23:39:30.000000000 -0700 @@ -46,7 +46,8 @@ private boolean needsResize; private boolean opaque = false; private int w, h; - private float pixelScaleFactor; + private float pixelScaleFactorX; + private float pixelScaleFactorY; // a value of zero corresponds to the windowing system-provided // framebuffer object int nativeDestHandle = 0; @@ -87,7 +88,8 @@ ES2SwapChain(ES2Context context, PresentableState pState) { this.context = context; this.pState = pState; - this.pixelScaleFactor = pState.getRenderScale(); + this.pixelScaleFactorX = pState.getRenderScaleX(); + this.pixelScaleFactorY = pState.getRenderScaleY(); this.msaa = pState.isMSAA(); long nativeWindow = pState.getNativeWindow(); drawable = ES2Pipeline.glFactory.createGLDrawable( @@ -95,7 +97,10 @@ } public boolean lockResources(PresentableState pState) { - if (this.pState != pState || pixelScaleFactor != pState.getRenderScale()) { + if (this.pState != pState || + pixelScaleFactorX != pState.getRenderScaleX() || + pixelScaleFactorY != pState.getRenderScaleY()) + { return true; } needsResize = (w != pState.getRenderWidth() || h != pState.getRenderHeight()); @@ -220,7 +225,7 @@ copyFullBuffer = true; } ES2Graphics g = ES2Graphics.create(context, stableBackbuffer); - g.scale(pixelScaleFactor, pixelScaleFactor); + g.scale(pixelScaleFactorX, pixelScaleFactorY); return g; } @@ -269,8 +274,14 @@ return pState.getOutputHeight(); } - public float getPixelScaleFactor() { - return pixelScaleFactor; + @Override + public float getPixelScaleFactorX() { + return pixelScaleFactorX; + } + + @Override + public float getPixelScaleFactorY() { + return pixelScaleFactorY; } @Override --- old/modules/graphics/src/main/java/com/sun/prism/impl/BaseGraphics.java 2016-03-30 23:39:31.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/impl/BaseGraphics.java 2016-03-30 23:39:31.000000000 -0700 @@ -81,7 +81,8 @@ private final BaseContext context; private final RenderTarget renderTarget; private boolean state3D = false; - private float pixelScale = 1.0f; + private float pixelScaleX = 1.0f; + private float pixelScaleY = 1.0f; protected BaseGraphics(BaseContext context, RenderTarget target) { this.context = context; @@ -274,13 +275,19 @@ } @Override - public void setPixelScaleFactor(float pixelScale) { - this.pixelScale = pixelScale; + public void setPixelScaleFactors(float pixelScaleX, float pixelScaleY) { + this.pixelScaleX = pixelScaleX; + this.pixelScaleY = pixelScaleY; } @Override - public float getPixelScaleFactor() { - return pixelScale; + public float getPixelScaleFactorX() { + return pixelScaleX; + } + + @Override + public float getPixelScaleFactorY() { + return pixelScaleY; } public void setCamera(NGCamera camera) { --- old/modules/graphics/src/main/java/com/sun/prism/impl/QueuedPixelSource.java 2016-03-30 23:39:32.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/impl/QueuedPixelSource.java 2016-03-30 23:39:32.000000000 -0700 @@ -113,10 +113,11 @@ * * @param w the width of the desired Pixels object * @param h the height of the desired Pixels object - * @param scale the scale of the desired Pixels object + * @param scalex the horizontal scale of the desired Pixels object + * @param scaley the vertical scale of the desired Pixels object * @return an unused {@code Pixels} object */ - public synchronized Pixels getUnusedPixels(int w, int h, float scale) { + public synchronized Pixels getUnusedPixels(int w, int h, float scalex, float scaley) { int i = 0; IntBuffer reuseBuffer = null; while (i < saved.size()) { @@ -132,7 +133,8 @@ } if (p.getWidthUnsafe() == w && p.getHeightUnsafe() == h && - p.getScaleUnsafe() == scale) + p.getScaleXUnsafe() == scalex && + p.getScaleYUnsafe() == scaley) { return p; } @@ -155,7 +157,7 @@ reuseBuffer = IntBuffer.allocate(bufsize); } } - Pixels p = Application.GetApplication().createPixels(w, h, reuseBuffer, scale); + Pixels p = Application.GetApplication().createPixels(w, h, reuseBuffer, scalex, scaley); saved.add(new WeakReference<>(p)); return p; } --- old/modules/graphics/src/main/java/com/sun/prism/j2d/J2DPresentable.java 2016-03-30 23:39:33.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/j2d/J2DPresentable.java 2016-03-30 23:39:33.000000000 -0700 @@ -114,7 +114,7 @@ */ int w = getPhysicalWidth(); int h = getPhysicalHeight(); - pixels = pixelSource.getUnusedPixels(w, h, 1.0f); + pixels = pixelSource.getUnusedPixels(w, h, 1.0f, 1.0f); IntBuffer pixBuf = (IntBuffer) pixels.getPixels(); assert ib.hasArray(); System.arraycopy(ib.array(), 0, pixBuf.array(), 0, w*h); @@ -255,7 +255,13 @@ return 0; } - public float getPixelScaleFactor() { + @Override + public float getPixelScaleFactorX() { + return 1.0f; + } + + @Override + public float getPixelScaleFactorY() { return 1.0f; } --- old/modules/graphics/src/main/java/com/sun/prism/j2d/J2DPrismGraphics.java 2016-03-30 23:39:34.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/j2d/J2DPrismGraphics.java 2016-03-30 23:39:34.000000000 -0700 @@ -116,7 +116,8 @@ new java.awt.geom.AffineTransform(); private int clipRectIndex; private boolean hasPreCullingBits = false; - private float pixelScale = 1.0f; + private float pixelScaleX = 1.0f; + private float pixelScaleY = 1.0f; static java.awt.Color toJ2DColor(Color c) { return new java.awt.Color(c.getRed(), @@ -1383,13 +1384,19 @@ } @Override - public void setPixelScaleFactor(float pixelScale) { - this.pixelScale = pixelScale; + public void setPixelScaleFactors(float pixelScaleX, float pixelScaleY) { + this.pixelScaleX = pixelScaleX; + this.pixelScaleY = pixelScaleY; } @Override - public float getPixelScaleFactor() { - return pixelScale; + public float getPixelScaleFactorX() { + return pixelScaleX; + } + + @Override + public float getPixelScaleFactorY() { + return pixelScaleY; } @Override --- old/modules/graphics/src/main/java/com/sun/prism/null3d/DummySwapChain.java 2016-03-30 23:39:35.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/null3d/DummySwapChain.java 2016-03-30 23:39:35.000000000 -0700 @@ -90,7 +90,13 @@ return 0; } - public float getPixelScaleFactor() { + @Override + public float getPixelScaleFactorX() { + return 1.0f; + } + + @Override + public float getPixelScaleFactorY() { return 1.0f; } --- old/modules/graphics/src/main/java/com/sun/prism/sw/SWGraphics.java 2016-03-30 23:39:37.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/sw/SWGraphics.java 2016-03-30 23:39:36.000000000 -0700 @@ -92,7 +92,8 @@ private boolean antialiasedShape = true; private boolean hasPreCullingBits = false; - private float pixelScale = 1.0f; + private float pixelScaleX = 1.0f; + private float pixelScaleY = 1.0f; private NodePath renderRoot; @Override @@ -926,13 +927,18 @@ } @Override - public void setPixelScaleFactor(float pixelScale) { - this.pixelScale = pixelScale; + public void setPixelScaleFactors(float pixelScaleX, float pixelScaleY) { + this.pixelScaleX = pixelScaleX; } @Override - public float getPixelScaleFactor() { - return pixelScale; + public float getPixelScaleFactorX() { + return pixelScaleX; + } + + @Override + public float getPixelScaleFactorY() { + return pixelScaleY; } @Override --- old/modules/graphics/src/main/java/com/sun/prism/sw/SWPresentable.java 2016-03-30 23:39:38.000000000 -0700 +++ new/modules/graphics/src/main/java/com/sun/prism/sw/SWPresentable.java 2016-03-30 23:39:37.000000000 -0700 @@ -58,7 +58,7 @@ */ int w = getPhysicalWidth(); int h = getPhysicalHeight(); - pixels = pixelSource.getUnusedPixels(w, h, 1.0f); + pixels = pixelSource.getUnusedPixels(w, h, 1.0f, 1.0f); IntBuffer pixBuf = (IntBuffer) pixels.getPixels(); IntBuffer buf = getSurface().getDataIntBuffer(); assert buf.hasArray(); @@ -75,8 +75,14 @@ return true; } - public float getPixelScaleFactor() { - return pState.getRenderScale(); + @Override + public float getPixelScaleFactorX() { + return pState.getRenderScaleX(); + } + + @Override + public float getPixelScaleFactorY() { + return pState.getRenderScaleY(); } public int getContentWidth() { --- old/modules/graphics/src/main/java/javafx/scene/layout/BorderPane.java 2016-03-30 23:39:39.000000000 -0700 +++ new/modules/graphics/src/main/java/javafx/scene/layout/BorderPane.java 2016-03-30 23:39:39.000000000 -0700 @@ -512,14 +512,14 @@ Insets topMargin = getNodeMargin(t); double adjustedWidth = adjustWidthByMargin(insideWidth, topMargin); double adjustedHeight = adjustHeightByMargin(insideHeight, topMargin); - topHeight = snapSize(t.prefHeight(adjustedWidth)); + topHeight = snapSizeY(t.prefHeight(adjustedWidth)); topHeight = Math.min(topHeight, adjustedHeight); Vec2d result = boundedNodeSizeWithBias(t, adjustedWidth, topHeight, true, true, TEMP_VEC2D); - topHeight = snapSize(result.y); - t.resize(snapSize(result.x), topHeight); + topHeight = snapSizeY(result.y); + t.resize(snapSizeX(result.x), topHeight); - topHeight = snapSpace(topMargin.getBottom()) + topHeight + snapSpace(topMargin.getTop()); + topHeight = snapSpaceY(topMargin.getBottom()) + topHeight + snapSpaceY(topMargin.getTop()); Pos alignment = getAlignment(t); positionInArea(t, insideX, insideY, insideWidth, topHeight, 0/*ignore baseline*/, topMargin, @@ -532,14 +532,14 @@ Insets bottomMargin = getNodeMargin(b); double adjustedWidth = adjustWidthByMargin(insideWidth, bottomMargin); double adjustedHeight = adjustHeightByMargin(insideHeight - topHeight, bottomMargin); - bottomHeight = snapSize(b.prefHeight(adjustedWidth)); + bottomHeight = snapSizeY(b.prefHeight(adjustedWidth)); bottomHeight = Math.min(bottomHeight, adjustedHeight); Vec2d result = boundedNodeSizeWithBias(b, adjustedWidth, bottomHeight, true, true, TEMP_VEC2D); - bottomHeight = snapSize(result.y); - b.resize(snapSize(result.x), bottomHeight); + bottomHeight = snapSizeY(result.y); + b.resize(snapSizeX(result.x), bottomHeight); - bottomHeight = snapSpace(bottomMargin.getBottom()) + bottomHeight + snapSpace(bottomMargin.getTop()); + bottomHeight = snapSpaceY(bottomMargin.getBottom()) + bottomHeight + snapSpaceY(bottomMargin.getTop()); Pos alignment = getAlignment(b); positionInArea(b, insideX, insideY + insideHeight - bottomHeight, insideWidth, bottomHeight, 0/*ignore baseline*/, @@ -553,14 +553,14 @@ Insets leftMargin = getNodeMargin(l); double adjustedWidth = adjustWidthByMargin(insideWidth, leftMargin); double adjustedHeight = adjustHeightByMargin(insideHeight - topHeight - bottomHeight, leftMargin); // ???? - leftWidth = snapSize(l.prefWidth(adjustedHeight)); + leftWidth = snapSizeX(l.prefWidth(adjustedHeight)); leftWidth = Math.min(leftWidth, adjustedWidth); Vec2d result = boundedNodeSizeWithBias(l, leftWidth, adjustedHeight, true, true, TEMP_VEC2D); - leftWidth = snapSize(result.x); - l.resize(leftWidth, snapSize(result.y)); + leftWidth = snapSizeX(result.x); + l.resize(leftWidth, snapSizeY(result.y)); - leftWidth = snapSpace(leftMargin.getLeft()) + leftWidth + snapSpace(leftMargin.getRight()); + leftWidth = snapSpaceX(leftMargin.getLeft()) + leftWidth + snapSpaceX(leftMargin.getRight()); Pos alignment = getAlignment(l); positionInArea(l, insideX, insideY + topHeight, leftWidth, insideHeight - topHeight - bottomHeight, 0/*ignore baseline*/, @@ -575,14 +575,14 @@ double adjustedWidth = adjustWidthByMargin(insideWidth - leftWidth, rightMargin); double adjustedHeight = adjustHeightByMargin(insideHeight - topHeight - bottomHeight, rightMargin); - rightWidth = snapSize(r.prefWidth(adjustedHeight)); + rightWidth = snapSizeX(r.prefWidth(adjustedHeight)); rightWidth = Math.min(rightWidth, adjustedWidth); Vec2d result = boundedNodeSizeWithBias(r, rightWidth, adjustedHeight, true, true, TEMP_VEC2D); - rightWidth = snapSize(result.x); - r.resize(rightWidth, snapSize(result.y)); + rightWidth = snapSizeX(result.x); + r.resize(rightWidth, snapSizeY(result.y)); - rightWidth = snapSpace(rightMargin.getLeft()) + rightWidth + snapSpace(rightMargin.getRight()); + rightWidth = snapSpaceX(rightMargin.getLeft()) + rightWidth + snapSpaceX(rightMargin.getRight()); Pos alignment = getAlignment(r); positionInArea(r, insideX + insideWidth - rightWidth, insideY + topHeight, rightWidth, insideHeight - topHeight - bottomHeight, 0/*ignore baseline*/, --- old/modules/graphics/src/main/java/javafx/scene/layout/FlowPane.java 2016-03-30 23:39:40.000000000 -0700 +++ new/modules/graphics/src/main/java/javafx/scene/layout/FlowPane.java 2016-03-30 23:39:40.000000000 -0700 @@ -569,7 +569,7 @@ } } final Insets insets = getInsets(); - return insets.getLeft() + snapSize(maxPref) + insets.getRight(); + return insets.getLeft() + snapSizeX(maxPref) + insets.getRight(); } return computePrefWidth(height); } @@ -585,7 +585,7 @@ } } final Insets insets = getInsets(); - return insets.getTop() + snapSize(maxPref) + insets.getBottom(); + return insets.getTop() + snapSizeY(maxPref) + insets.getBottom(); } return computePrefHeight(width); } @@ -598,7 +598,7 @@ List hruns = getRuns(maxRunWidth); double w = computeContentWidth(hruns); w = getPrefWrapLength() > w ? getPrefWrapLength() : w; - return insets.getLeft() + snapSize(w) + insets.getRight(); + return insets.getLeft() + snapSizeX(w) + insets.getRight(); } else { // vertical double maxRunHeight = forHeight != -1? @@ -622,7 +622,7 @@ List vruns = getRuns(maxRunHeight); double h = computeContentHeight(vruns); h = getPrefWrapLength() > h ? getPrefWrapLength() : h; - return insets.getTop() + snapSize(h) + insets.getBottom(); + return insets.getTop() + snapSizeY(h) + insets.getBottom(); } } @@ -645,8 +645,8 @@ double runLength = 0; double runOffset = 0; Run run = new Run(); - double vgap = snapSpace(this.getVgap()); - double hgap = snapSpace(this.getHgap()); + double vgap = snapSpaceY(this.getVgap()); + double hgap = snapSpaceX(this.getHgap()); final List children = getChildren(); for (int i=0, size=children.size(); i rownodes = new ArrayList(); - run.width = (run.rects.size()-1)*snapSpace(getHgap()); + run.width = (run.rects.size()-1)*snapSpaceX(getHgap()); for (int i=0, max=run.rects.size(); i runs) { - double cwidth = getOrientation() == HORIZONTAL ? 0 : (runs.size()-1)*snapSpace(getHgap()); + double cwidth = getOrientation() == HORIZONTAL ? 0 : (runs.size()-1)*snapSpaceX(getHgap()); for (int i=0, max=runs.size(); i runs) { - double cheight = getOrientation() == VERTICAL ? 0 : (runs.size()-1)*snapSpace(getVgap()); + double cheight = getOrientation() == VERTICAL ? 0 : (runs.size()-1)*snapSpaceY(getVgap()); for (int i=0, max=runs.size(); i= 0 ) { rowMaxHeight.setPresetSize(i, boundedSize(min, maxRowHeight, maxRowHeight)); } else { @@ -1396,10 +1396,10 @@ final ObservableList rowConstr = getRowConstraints(); for (int i = 0; i < rowConstr.size(); ++i) { final RowConstraints curConstraint = rowConstr.get(i); - double prefRowHeight = snapSize(curConstraint.getPrefHeight()); - final double min = snapSize(curConstraint.getMinHeight()); + double prefRowHeight = snapSizeY(curConstraint.getPrefHeight()); + final double min = snapSizeY(curConstraint.getMinHeight()); if (prefRowHeight != USE_COMPUTED_SIZE) { - final double max = snapSize(curConstraint.getMaxHeight()); + final double max = snapSizeY(curConstraint.getMaxHeight()); if (min >= 0 || max >= 0) { result.setPresetSize(i, boundedSize(min < 0 ? 0 : min, prefRowHeight, @@ -1444,7 +1444,7 @@ final ObservableList rowConstr = getRowConstraints(); CompositeSize prefHeights = null; for (int i = 0; i < rowConstr.size(); ++i) { - double minRowHeight = snapSize(rowConstr.get(i).getMinHeight()); + double minRowHeight = snapSizeY(rowConstr.get(i).getMinHeight()); if (minRowHeight == USE_PREF_SIZE) { if (prefHeights == null) { prefHeights = computePrefHeights(widths); @@ -1491,14 +1491,14 @@ CompositeSize prefWidths = null; for (int i = 0; i < columnConstr.size(); ++i) { final ColumnConstraints curConstraint = columnConstr.get(i); - double maxColumnWidth = snapSize(curConstraint.getMaxWidth()); + double maxColumnWidth = snapSizeX(curConstraint.getMaxWidth()); if (maxColumnWidth == USE_PREF_SIZE) { if (prefWidths == null) { prefWidths = computePrefWidths(null); } columnMaxWidth.setPresetSize(i, prefWidths.getSize(i)); } else if (maxColumnWidth != USE_COMPUTED_SIZE) { - final double min = snapSize(curConstraint.getMinWidth()); + final double min = snapSizeX(curConstraint.getMinWidth()); if (min >= 0) { columnMaxWidth.setPresetSize(i, boundedSize(min, maxColumnWidth, maxColumnWidth)); } else { @@ -1525,10 +1525,10 @@ final ObservableList columnConstr = getColumnConstraints(); for (int i = 0; i < columnConstr.size(); ++i) { final ColumnConstraints curConstraint = columnConstr.get(i); - double prefColumnWidth = snapSize(curConstraint.getPrefWidth()); - final double min = snapSize(curConstraint.getMinWidth()); + double prefColumnWidth = snapSizeX(curConstraint.getPrefWidth()); + final double min = snapSizeX(curConstraint.getMinWidth()); if (prefColumnWidth != USE_COMPUTED_SIZE) { - final double max = snapSize(curConstraint.getMaxWidth()); + final double max = snapSizeX(curConstraint.getMaxWidth()); if (min >= 0 || max >= 0) { result.setPresetSize(i, boundedSize(min < 0 ? 0 : min, prefColumnWidth, @@ -1576,7 +1576,7 @@ final ObservableList columnConstr = getColumnConstraints(); CompositeSize prefWidths = null; for (int i = 0; i < columnConstr.size(); ++i) { - double minColumnWidth = snapSize(columnConstr.get(i).getMinWidth()); + double minColumnWidth = snapSizeX(columnConstr.get(i).getMinWidth()); if (minColumnWidth == USE_PREF_SIZE) { if (prefWidths == null) { prefWidths = computePrefWidths(heights); @@ -1663,12 +1663,12 @@ @Override protected void layoutChildren() { performingLayout = true; try { - final double snaphgap = snapSpace(getHgap()); - final double snapvgap = snapSpace(getVgap()); - final double top = snapSpace(getInsets().getTop()); - final double bottom = snapSpace(getInsets().getBottom()); - final double left = snapSpace(getInsets().getLeft()); - final double right = snapSpace(getInsets().getRight()); + final double snaphgap = snapSpaceX(getHgap()); + final double snapvgap = snapSpaceY(getVgap()); + final double top = snapSpaceY(getInsets().getTop()); + final double bottom = snapSpaceY(getInsets().getBottom()); + final double left = snapSpaceX(getInsets().getLeft()); + final double right = snapSpaceX(getInsets().getRight()); final double width = getWidth(); final double height = getHeight(); @@ -1799,9 +1799,9 @@ private double adjustRowHeights(final CompositeSize heights, double height) { assert(height != -1); - final double snapvgap = snapSpace(getVgap()); - final double top = snapSpace(getInsets().getTop()); - final double bottom = snapSpace(getInsets().getBottom()); + final double snapvgap = snapSpaceY(getVgap()); + final double top = snapSpaceY(getInsets().getTop()); + final double bottom = snapSpaceY(getInsets().getBottom()); final double vgaps = snapvgap * (getNumberOfRows() - 1); final double contentHeight = height - top - bottom; @@ -2004,7 +2004,7 @@ if (portion != 0) { for (Iterator i = adjusting.iterator(); i.hasNext();) { final int index = i.next(); - double limit = snapSpace(limitSize.getProportionalMinOrMaxSize(index, shrinking)) + double limit = snapSpaceY(limitSize.getProportionalMinOrMaxSize(index, shrinking)) - heights.getSize(index); // negative in shrinking case if (shrinking && limit > 0 || !shrinking && limit < 0) { // Limit completely if current size @@ -2040,9 +2040,9 @@ private double adjustColumnWidths(final CompositeSize widths, double width) { assert(width != -1); - final double snaphgap = snapSpace(getHgap()); - final double left = snapSpace(getInsets().getLeft()); - final double right = snapSpace(getInsets().getRight()); + final double snaphgap = snapSpaceX(getHgap()); + final double left = snapSpaceX(getInsets().getLeft()); + final double right = snapSpaceX(getInsets().getRight()); final double hgaps = snaphgap * (getNumberOfColumns() - 1); final double contentWidth = width - left - right; @@ -2248,7 +2248,7 @@ if (portion != 0) { for (Iterator i = adjusting.iterator(); i.hasNext();) { final int index = i.next(); - double limit = snapSpace(limitSize.getProportionalMinOrMaxSize(index, shrinking)) + double limit = snapSpaceX(limitSize.getProportionalMinOrMaxSize(index, shrinking)) - widths.getSize(index); // negative in shrinking case if (shrinking && limit > 0 || !shrinking && limit < 0) { // Limit completely if current size @@ -2289,8 +2289,8 @@ if (!gridLines.getChildren().isEmpty()) { gridLines.getChildren().clear(); } - double hgap = snapSpace(getHgap()); - double vgap = snapSpace(getVgap()); + double hgap = snapSpaceX(getHgap()); + double vgap = snapSpaceY(getVgap()); // create vertical lines double linex = x; @@ -2341,12 +2341,12 @@ private CompositeSize createCompositeRows(double initSize) { return new CompositeSize(getNumberOfRows(), rowPercentHeight, rowPercentTotal, - snapSpace(getVgap()), initSize); + snapSpaceY(getVgap()), initSize); } private CompositeSize createCompositeColumns(double initSize) { return new CompositeSize(getNumberOfColumns(), columnPercentWidth, columnPercentTotal, - snapSpace(getHgap()), initSize); + snapSpaceX(getHgap()), initSize); } private int getNodeRowEndConvertRemaining(Node child) { @@ -2740,14 +2740,14 @@ */ @Deprecated // SB-dependency: RT-33381 has been filed to track this public final Bounds impl_getCellBounds(int columnIndex, int rowIndex) { - final double snaphgap = this.snapSpace(this.getHgap()); - final double snapvgap = this.snapSpace(this.getVgap()); - final double top = this.snapSpace(this.getInsets().getTop()); - final double right = this.snapSpace(this.getInsets().getRight()); - final double bottom = this.snapSpace(this.getInsets().getBottom()); - final double left = this.snapSpace(this.getInsets().getLeft()); - final double gridPaneHeight = this.snapSize(this.getHeight()) - (top + bottom); - final double gridPaneWidth = this.snapSize(this.getWidth()) - (left + right); + final double snaphgap = this.snapSpaceX(this.getHgap()); + final double snapvgap = this.snapSpaceY(this.getVgap()); + final double top = this.snapSpaceY(this.getInsets().getTop()); + final double right = this.snapSpaceX(this.getInsets().getRight()); + final double bottom = this.snapSpaceY(this.getInsets().getBottom()); + final double left = this.snapSpaceX(this.getInsets().getLeft()); + final double gridPaneHeight = this.snapSizeY(this.getHeight()) - (top + bottom); + final double gridPaneWidth = this.snapSizeX(this.getWidth()) - (left + right); // Compute grid. Result contains two double arrays, first for columns, second for rows double[] columnWidths; --- old/modules/graphics/src/main/java/javafx/scene/layout/HBox.java 2016-03-30 23:39:42.000000000 -0700 +++ new/modules/graphics/src/main/java/javafx/scene/layout/HBox.java 2016-03-30 23:39:42.000000000 -0700 @@ -396,9 +396,9 @@ @Override protected double computeMinWidth(double height) { Insets insets = getInsets(); - return snapSpace(insets.getLeft()) + + return snapSpaceX(insets.getLeft()) + computeContentWidth(getManagedChildren(), height, true) + - snapSpace(insets.getRight()); + snapSpaceX(insets.getRight()); } @Override protected double computeMinHeight(double width) { @@ -412,16 +412,16 @@ } else { contentHeight = computeMaxMinAreaHeight(managed, marginAccessor, getAlignmentInternal().getVpos()); } - return snapSpace(insets.getTop()) + + return snapSpaceY(insets.getTop()) + contentHeight + - snapSpace(insets.getBottom()); + snapSpaceY(insets.getBottom()); } @Override protected double computePrefWidth(double height) { Insets insets = getInsets(); - return snapSpace(insets.getLeft()) + + return snapSpaceX(insets.getLeft()) + computeContentWidth(getManagedChildren(), height, false) + - snapSpace(insets.getRight()); + snapSpaceX(insets.getRight()); } @Override protected double computePrefHeight(double width) { @@ -435,16 +435,16 @@ } else { contentHeight = computeMaxPrefAreaHeight(managed, marginAccessor, getAlignmentInternal().getVpos()); } - return snapSpace(insets.getTop()) + + return snapSpaceY(insets.getTop()) + contentHeight + - snapSpace(insets.getBottom()); + snapSpaceY(insets.getBottom()); } private double[][] getAreaWidths(Listmanaged, double height, boolean minimum) { // height could be -1 double[][] temp = getTempArray(managed.size()); final double insideHeight = height == -1? -1 : height - - snapSpace(getInsets().getTop()) - snapSpace(getInsets().getBottom()); + snapSpaceY(getInsets().getTop()) - snapSpaceY(getInsets().getBottom()); final boolean shouldFillHeight = shouldFillHeight(); for (int i = 0, size = managed.size(); i < size; i++) { Node child = managed.get(i); @@ -460,12 +460,12 @@ private double adjustAreaWidths(Listmanaged, double areaWidths[][], double width, double height) { Insets insets = getInsets(); - double top = snapSpace(insets.getTop()); - double bottom = snapSpace(insets.getBottom()); + double top = snapSpaceY(insets.getTop()); + double bottom = snapSpaceY(insets.getBottom()); - double contentWidth = sum(areaWidths[0], managed.size()) + (managed.size()-1)*snapSpace(getSpacing()); + double contentWidth = sum(areaWidths[0], managed.size()) + (managed.size()-1)*snapSpaceX(getSpacing()); double extraWidth = width - - snapSpace(insets.getLeft()) - snapSpace(insets.getRight()) - contentWidth; + snapSpaceX(insets.getLeft()) - snapSpaceX(insets.getRight()) - contentWidth; if (extraWidth != 0) { final double refHeight = shouldFillHeight() && height != -1? height - top - bottom : -1; @@ -504,7 +504,7 @@ double available = extraWidth; // will be negative in shrinking case outer:while (Math.abs(available) > 1 && adjustingNumber > 0) { - final double portion = snapPortion(available / adjustingNumber); // negative in shrinking case + final double portion = snapPortionX(available / adjustingNumber); // negative in shrinking case for (int i = 0, size = managed.size(); i < size; i++) { if (temp[i] == -1) { continue; @@ -528,7 +528,7 @@ private double computeContentWidth(List managedChildren, double height, boolean minimum) { return sum(getAreaWidths(managedChildren, height, minimum)[0], managedChildren.size()) - + (managedChildren.size()-1)*snapSpace(getSpacing()); + + (managedChildren.size()-1)*snapSpaceX(getSpacing()); } private static double sum(double[] array, int size) { @@ -615,11 +615,11 @@ VPos alignVpos = align.getVpos(); double width = getWidth(); double height = getHeight(); - double top = snapSpace(insets.getTop()); - double left = snapSpace(insets.getLeft()); - double bottom = snapSpace(insets.getBottom()); - double right = snapSpace(insets.getRight()); - double space = snapSpace(getSpacing()); + double top = snapSpaceY(insets.getTop()); + double left = snapSpaceX(insets.getLeft()); + double bottom = snapSpaceY(insets.getBottom()); + double right = snapSpaceX(insets.getRight()); + double space = snapSpaceX(getSpacing()); boolean shouldFillHeight = shouldFillHeight(); final double[][] actualAreaWidths = getAreaWidths(managed, height, false); --- old/modules/graphics/src/main/java/javafx/scene/layout/TilePane.java 2016-03-30 23:39:44.000000000 -0700 +++ new/modules/graphics/src/main/java/javafx/scene/layout/TilePane.java 2016-03-30 23:39:44.000000000 -0700 @@ -799,14 +799,14 @@ if (forHeight != -1) { // first compute number of rows that will fit in given height and // compute pref columns from that - int prefRows = computeRows(forHeight - snapSpace(insets.getTop()) - snapSpace(insets.getBottom()), getTileHeight()); + int prefRows = computeRows(forHeight - snapSpaceY(insets.getTop()) - snapSpaceY(insets.getBottom()), getTileHeight()); prefCols = computeOther(managed.size(), prefRows); } else { prefCols = getOrientation() == HORIZONTAL? getPrefColumns() : computeOther(managed.size(), getPrefRows()); } - return snapSpace(insets.getLeft()) + + return snapSpaceX(insets.getLeft()) + computeContentWidth(prefCols, getTileWidth()) + - snapSpace(insets.getRight()); + snapSpaceX(insets.getRight()); } @Override protected double computePrefHeight(double forWidth) { @@ -816,14 +816,14 @@ if (forWidth != -1) { // first compute number of columns that will fit in given width and // compute pref rows from that - int prefCols = computeColumns(forWidth - snapSpace(insets.getLeft()) - snapSpace(insets.getRight()), getTileWidth()); + int prefCols = computeColumns(forWidth - snapSpaceX(insets.getLeft()) - snapSpaceX(insets.getRight()), getTileWidth()); prefRows = computeOther(managed.size(), prefCols); } else { prefRows = getOrientation() == HORIZONTAL? computeOther(managed.size(), getPrefColumns()) : getPrefRows(); } - return snapSpace(insets.getTop()) + + return snapSpaceY(insets.getTop()) + computeContentHeight(prefRows, getTileHeight()) + - snapSpace(insets.getBottom()); + snapSpaceY(insets.getBottom()); } private double computeTileWidth() { @@ -843,9 +843,9 @@ // widest may depend on height of tile h = computeMaxPrefAreaHeight(managed, marginAccessor, -1, getTileAlignmentInternal().getVpos()); } - return snapSize(computeMaxPrefAreaWidth(managed, marginAccessor, h, true)); + return snapSizeX(computeMaxPrefAreaWidth(managed, marginAccessor, h, true)); } - return snapSize(preftilewidth); + return snapSizeX(preftilewidth); } private double computeTileHeight() { @@ -865,9 +865,9 @@ // tallest may depend on width of tile w = computeMaxPrefAreaWidth(managed, marginAccessor); } - return snapSize(computeMaxPrefAreaHeight(managed, marginAccessor, w, getTileAlignmentInternal().getVpos())); + return snapSizeY(computeMaxPrefAreaHeight(managed, marginAccessor, w, getTileAlignmentInternal().getVpos())); } - return snapSize(preftileheight); + return snapSizeY(preftileheight); } private int computeOther(int numNodes, int numCells) { @@ -876,21 +876,23 @@ } private int computeColumns(double width, double tilewidth) { - return Math.max(1,(int)((width + snapSpace(getHgap())) / (tilewidth + snapSpace(getHgap())))); + double snappedHgap = snapSpaceX(getHgap()); + return Math.max(1,(int)((width + snappedHgap) / (tilewidth + snappedHgap))); } private int computeRows(double height, double tileheight) { - return Math.max(1, (int)((height + snapSpace(getVgap())) / (tileheight + snapSpace(getVgap())))); + double snappedVgap = snapSpaceY(getVgap()); + return Math.max(1, (int)((height + snappedVgap) / (tileheight + snappedVgap))); } private double computeContentWidth(int columns, double tilewidth) { if (columns == 0) return 0; - return columns * tilewidth + (columns - 1) * snapSpace(getHgap()); + return columns * tilewidth + (columns - 1) * snapSpaceX(getHgap()); } private double computeContentHeight(int rows, double tileheight) { if (rows == 0) return 0; - return rows * tileheight + (rows - 1) * snapSpace(getVgap()); + return rows * tileheight + (rows - 1) * snapSpaceY(getVgap()); } @Override protected void layoutChildren() { @@ -899,12 +901,12 @@ VPos vpos = getAlignmentInternal().getVpos(); double width = getWidth(); double height = getHeight(); - double top = snapSpace(getInsets().getTop()); - double left = snapSpace(getInsets().getLeft()); - double bottom = snapSpace(getInsets().getBottom()); - double right = snapSpace(getInsets().getRight()); - double vgap = snapSpace(getVgap()); - double hgap = snapSpace(getHgap()); + double top = snapSpaceY(getInsets().getTop()); + double left = snapSpaceX(getInsets().getLeft()); + double bottom = snapSpaceY(getInsets().getBottom()); + double right = snapSpaceX(getInsets().getRight()); + double vgap = snapSpaceY(getVgap()); + double hgap = snapSpaceX(getHgap()); double insideWidth = width - left - right; double insideHeight = height - top - bottom; --- old/modules/graphics/src/main/java/javafx/scene/layout/VBox.java 2016-03-30 23:39:45.000000000 -0700 +++ new/modules/graphics/src/main/java/javafx/scene/layout/VBox.java 2016-03-30 23:39:45.000000000 -0700 @@ -387,14 +387,14 @@ } else { contentWidth = computeMaxMinAreaWidth(managed, marginAccessor); } - return snapSpace(insets.getLeft()) + contentWidth + snapSpace(insets.getRight()); + return snapSpaceX(insets.getLeft()) + contentWidth + snapSpaceX(insets.getRight()); } @Override protected double computeMinHeight(double width) { Insets insets = getInsets(); - return snapSpace(insets.getTop()) + + return snapSpaceY(insets.getTop()) + computeContentHeight(getManagedChildren(), width, true) + - snapSpace(insets.getBottom()); + snapSpaceY(insets.getBottom()); } @Override protected double computePrefWidth(double height) { @@ -408,14 +408,14 @@ } else { contentWidth = computeMaxPrefAreaWidth(managed, marginAccessor); } - return snapSpace(insets.getLeft()) + contentWidth + snapSpace(insets.getRight()); + return snapSpaceX(insets.getLeft()) + contentWidth + snapSpaceX(insets.getRight()); } @Override protected double computePrefHeight(double width) { Insets insets = getInsets(); - double d = snapSpace(insets.getTop()) + + double d = snapSpaceY(insets.getTop()) + computeContentHeight(getManagedChildren(), width, false) + - snapSpace(insets.getBottom()); + snapSpaceY(insets.getBottom()); return d; } @@ -424,7 +424,7 @@ // width could be -1 double[][] temp = getTempArray(managed.size()); final double insideWidth = width == -1? -1 : width - - snapSpace(getInsets().getLeft()) - snapSpace(getInsets().getRight()); + snapSpaceX(getInsets().getLeft()) - snapSpaceX(getInsets().getRight()); final boolean isFillWidth = isFillWidth(); for (int i = 0, size = managed.size(); i < size; i++) { Node child = managed.get(i); @@ -448,12 +448,12 @@ private double adjustAreaHeights(Listmanaged, double areaHeights[][], double height, double width) { Insets insets = getInsets(); - double left = snapSpace(insets.getLeft()); - double right = snapSpace(insets.getRight()); + double left = snapSpaceX(insets.getLeft()); + double right = snapSpaceX(insets.getRight()); - double contentHeight = sum(areaHeights[0], managed.size()) + (managed.size()-1)*snapSpace(getSpacing()); + double contentHeight = sum(areaHeights[0], managed.size()) + (managed.size()-1)*snapSpaceY(getSpacing()); double extraHeight = height - - snapSpace(insets.getTop()) - snapSpace(insets.getBottom()) - contentHeight; + snapSpaceY(insets.getTop()) - snapSpaceY(insets.getBottom()) - contentHeight; if (extraHeight != 0) { final double refWidth = isFillWidth()&& width != -1? width - left - right : -1; @@ -492,7 +492,7 @@ double available = extraHeight; // will be negative in shrinking case outer: while (Math.abs(available) > 1 && adjustingNumber > 0) { - final double portion = snapPortion(available / adjustingNumber); // negative in shrinking case + final double portion = snapPortionY(available / adjustingNumber); // negative in shrinking case for (int i = 0, size = managed.size(); i < size; i++) { if (temp[i] == -1) { continue; @@ -516,7 +516,7 @@ private double computeContentHeight(List managedChildren, double width, boolean minimum) { return sum(getAreaHeights(managedChildren, width, minimum)[0], managedChildren.size()) - + (managedChildren.size()-1)*snapSpace(getSpacing()); + + (managedChildren.size()-1)*snapSpaceY(getSpacing()); } private static double sum(double[] array, int size) { @@ -543,11 +543,11 @@ Insets insets = getInsets(); double width = getWidth(); double height = getHeight(); - double top = snapSpace(insets.getTop()); - double left = snapSpace(insets.getLeft()); - double bottom = snapSpace(insets.getBottom()); - double right = snapSpace(insets.getRight()); - double space = snapSpace(getSpacing()); + double top = snapSpaceY(insets.getTop()); + double left = snapSpaceX(insets.getLeft()); + double bottom = snapSpaceY(insets.getBottom()); + double right = snapSpaceX(insets.getRight()); + double space = snapSpaceY(getSpacing()); HPos hpos = getAlignmentInternal().getHpos(); VPos vpos = getAlignmentInternal().getVpos(); boolean isFillWidth = isFillWidth(); --- old/modules/graphics/src/main/java/javafx/scene/text/TextFlow.java 2016-03-30 23:39:47.000000000 -0700 +++ new/modules/graphics/src/main/java/javafx/scene/text/TextFlow.java 2016-03-30 23:39:47.000000000 -0700 @@ -234,8 +234,8 @@ if (value != getWidth()) { TextLayout layout = getTextLayout(); Insets insets = getInsets(); - double left = snapSpace(insets.getLeft()); - double right = snapSpace(insets.getRight()); + double left = snapSpaceX(insets.getLeft()); + double right = snapSpaceX(insets.getRight()); double width = Math.max(1, value - left - right); layout.setWrapWidth((float)width); super.setWidth(value); @@ -247,8 +247,8 @@ layout.setWrapWidth(0); double width = layout.getBounds().getWidth(); Insets insets = getInsets(); - double left = snapSpace(insets.getLeft()); - double right = snapSpace(insets.getRight()); + double left = snapSpaceX(insets.getLeft()); + double right = snapSpaceX(insets.getRight()); double wrappingWidth = Math.max(1, getWidth() - left - right); layout.setWrapWidth((float)wrappingWidth); return left + width + right; @@ -257,8 +257,8 @@ @Override protected double computePrefHeight(double width) { TextLayout layout = getTextLayout(); Insets insets = getInsets(); - double left = snapSpace(insets.getLeft()); - double right = snapSpace(insets.getRight()); + double left = snapSpaceX(insets.getLeft()); + double right = snapSpaceX(insets.getRight()); if (width == USE_COMPUTED_SIZE) { layout.setWrapWidth(0); } else { @@ -268,8 +268,8 @@ double height = layout.getBounds().getHeight(); double wrappingWidth = Math.max(1, getWidth() - left - right); layout.setWrapWidth((float)wrappingWidth); - double top = snapSpace(insets.getTop()); - double bottom = snapSpace(insets.getBottom()); + double top = snapSpaceY(insets.getTop()); + double bottom = snapSpaceY(insets.getBottom()); return top + height + bottom; } @@ -313,8 +313,8 @@ @Override protected void layoutChildren() { inLayout = true; Insets insets = getInsets(); - double top = snapSpace(insets.getTop()); - double left = snapSpace(insets.getLeft()); + double top = snapSpaceY(insets.getTop()); + double left = snapSpaceX(insets.getLeft()); GlyphList[] runs = getTextLayout().getRuns(); for (int j = 0; j < runs.length; j++) { @@ -483,7 +483,7 @@ @Override public final double getBaselineOffset() { Insets insets = getInsets(); - double top = snapSpace(insets.getTop()); + double top = snapSpaceY(insets.getTop()); return top - getTextLayout().getBounds().getMinY(); } @@ -574,11 +574,11 @@ double right = margin != null? snapSpace(margin.getRight(), snap) : 0; double alt = -1; if (child.getContentBias() == Orientation.VERTICAL) { // width depends on height - alt = snapSize(boundedSize( + alt = snapSizeY(boundedSize( child.minHeight(-1), height != -1? height - top - bottom : child.prefHeight(-1), child.maxHeight(-1))); } - return left + snapSize(boundedSize(child.minWidth(alt), child.prefWidth(alt), child.maxWidth(alt))) + right; + return left + snapSizeX(boundedSize(child.minWidth(alt), child.prefWidth(alt), child.maxWidth(alt))) + right; } double computeChildPrefAreaHeight(Node child, Insets margin) { @@ -593,11 +593,11 @@ double right = margin != null? snapSpace(margin.getRight(), snap) : 0; double alt = -1; if (child.getContentBias() == Orientation.HORIZONTAL) { // height depends on width - alt = snapSize(boundedSize( + alt = snapSizeX(boundedSize( child.minWidth(-1), width != -1? width - left - right : child.prefWidth(-1), child.maxWidth(-1))); } - return top + snapSize(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom; + return top + snapSizeY(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom; } /* end of copied code */ --- old/modules/graphics/src/main/native-font/fontpath.c 2016-03-30 23:39:48.000000000 -0700 +++ new/modules/graphics/src/main/native-font/fontpath.c 2016-03-30 23:39:48.000000000 -0700 @@ -735,15 +735,19 @@ &fontSmoothingContrast, 0) ? fontSmoothingContrast : fontSmoothingContrastDefault; } -JNIEXPORT jint JNICALL +JNIEXPORT jfloat JNICALL Java_com_sun_javafx_font_PrismFontFactory_getSystemFontSizeNative(JNIEnv *env, jclass cl) { NONCLIENTMETRICSW ncmetrics; if (getSysParams(&ncmetrics)) { - return -ncmetrics.lfMessageFont.lfHeight; + HWND hWnd = GetDesktopWindow(); + HDC hDC = GetDC(hWnd); + int dpiY = GetDeviceCaps(hDC, LOGPIXELSY); + ReleaseDC(hWnd, hDC); + return (-ncmetrics.lfMessageFont.lfHeight) * 96.0f / dpiY; } else { - return 12; + return 12.0f; } } --- old/modules/graphics/src/main/native-glass/gtk/glass_general.cpp 2016-03-30 23:39:50.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/gtk/glass_general.cpp 2016-03-30 23:39:49.000000000 -0700 @@ -193,7 +193,7 @@ clazz = env->FindClass("com/sun/glass/ui/Screen"); if (env->ExceptionCheck()) return JNI_ERR; jScreenCls = (jclass) env->NewGlobalRef(clazz); - jScreenInit = env->GetMethodID(jScreenCls, "", "(JIIIIIIIIIIIF)V"); + jScreenInit = env->GetMethodID(jScreenCls, "", "(JIIIIIIIIIIIIIIIFFFF)V"); if (env->ExceptionCheck()) return JNI_ERR; jScreenNotifySettingsChanged = env->GetStaticMethodID(jScreenCls, "notifySettingsChanged", "()V"); if (env->ExceptionCheck()) return JNI_ERR; --- old/modules/graphics/src/main/native-glass/gtk/glass_screen.cpp 2016-03-30 23:39:51.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/gtk/glass_screen.cpp 2016-03-30 23:39:51.000000000 -0700 @@ -126,6 +126,11 @@ monitor_geometry.width, monitor_geometry.height, + monitor_geometry.x, + monitor_geometry.y, + monitor_geometry.width, + monitor_geometry.height, + working_monitor_geometry.x, working_monitor_geometry.y, working_monitor_geometry.width, @@ -133,7 +138,7 @@ (jint)gdk_screen_get_resolution(screen), (jint)gdk_screen_get_resolution(screen), - 1.0f); + 1.0f, 1.0f, 1.0f, 1.0f); JNI_EXCEPTION_TO_CPP(env); return jScreen; } --- old/modules/graphics/src/main/native-glass/ios/GlassScreen.m 2016-03-30 23:39:52.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/ios/GlassScreen.m 2016-03-30 23:39:52.000000000 -0700 @@ -36,8 +36,9 @@ { jmethodID screenInit = (*env)->GetMethodID(env, mat_jScreenClass, "", - "(JIIIIIIIIIIIF)V"); + "(JIIIIIIIIIIIIIIIFFFF)V"); + jfloat outputScale = (jfloat) [screen scale]; return (jobject)(*env)->NewObject(env, mat_jScreenClass, screenInit, ptr_to_jlong(screen), @@ -48,6 +49,11 @@ (jint)[screen bounds].size.width, (jint)[screen bounds].size.height, + (jint)[screen bounds].origin.x, + (jint)[screen bounds].origin.y, + (jint)[screen bounds].size.width, + (jint)[screen bounds].size.height, + (jint)[screen applicationFrame].origin.x, (jint)[screen applicationFrame].origin.y, (jint)[screen applicationFrame].size.width, @@ -56,7 +62,8 @@ (jint)[screen currentMode].size.width, (jint)[screen currentMode].size.height, - (jfloat)[screen scale]); + 1.0f, 1.0f, + outputScale, outputScale); } --- old/modules/graphics/src/main/native-glass/lens/LensScreen.c 2016-03-30 23:39:54.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/lens/LensScreen.c 2016-03-30 23:39:53.000000000 -0700 @@ -31,7 +31,7 @@ jmethodID screenInit = (*env)->GetMethodID(env, jScreenClass, "", - "(JIIIIIIIIIIIF)V"); + "(JIIIIIIIIIIIIIIIFFFF)V"); GLASS_CHECK_EXCEPTION(env); if (!screenInit) { @@ -49,6 +49,11 @@ screen->width, screen->height, + screen->x, + screen->y, + screen->width, + screen->height, + screen->visibleX, screen->visibleY, screen->visibleWidth, @@ -57,7 +62,7 @@ screen->resolutionX, screen->resolutionY, - 1.0f); + 1.0f, 1.0f, 1.0f, 1.0f); GLASS_CHECK_EXCEPTION(env); return newScreen; --- old/modules/graphics/src/main/native-glass/mac/GlassApplication.m 2016-03-30 23:39:55.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/mac/GlassApplication.m 2016-03-30 23:39:55.000000000 -0700 @@ -802,7 +802,7 @@ jApplicationClass = (*env)->NewGlobalRef(env, jClass); javaIDs.Application.createPixels = (*env)->GetStaticMethodID( - env, jClass, "createPixels", "(II[IF)Lcom/sun/glass/ui/Pixels;"); + env, jClass, "createPixels", "(II[IFF)Lcom/sun/glass/ui/Pixels;"); if ((*env)->ExceptionCheck(env)) return; javaIDs.Application.getScaleFactor = (*env)->GetStaticMethodID( --- old/modules/graphics/src/main/native-glass/mac/GlassRobot.m 2016-03-30 23:39:56.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/mac/GlassRobot.m 2016-03-30 23:39:56.000000000 -0700 @@ -488,7 +488,7 @@ // create Pixels pixels = (*env)->CallStaticObjectMethod(env, [GlassHelper ClassForName:"com.sun.glass.ui.Application" withEnv:env], - javaIDs.Application.createPixels, pixWidth, pixHeight, pixelArray, scale); + javaIDs.Application.createPixels, pixWidth, pixHeight, pixelArray, scale, scale); } } --- old/modules/graphics/src/main/native-glass/mac/GlassScreen.m 2016-03-30 23:39:57.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/mac/GlassScreen.m 2016-03-30 23:39:57.000000000 -0700 @@ -56,7 +56,7 @@ { jmethodID screenInit = (*env)->GetMethodID(env, jScreenClass, "", - "(JIIIIIIIIIIIF)V"); + "(JIIIIIIIIIIIIIIIFFFF)V"); GLASS_CHECK_EXCEPTION(env); // Note that NSDeviceResolution always reports 72 DPI, so we use Core Graphics API instead @@ -83,6 +83,7 @@ [screen retain]; } + jfloat scale = (jfloat)GetScreenScaleFactor(screen); jscreen = (jobject)(*env)->NewObject(env, jScreenClass, screenInit, ptr_to_jlong(screen), @@ -93,6 +94,11 @@ (jint)[screen frame].size.width, (jint)[screen frame].size.height, + (jint)[screen frame].origin.x, + (jint)(primaryFrame.size.height - [screen frame].size.height - [screen frame].origin.y), + (jint)[screen frame].size.width, + (jint)[screen frame].size.height, + (jint)[screen visibleFrame].origin.x, (jint)(primaryFrame.size.height - [screen visibleFrame].size.height - [screen visibleFrame].origin.y), (jint)[screen visibleFrame].size.width, @@ -101,7 +107,8 @@ (jint)resolution.width, (jint)resolution.height, - (jfloat)GetScreenScaleFactor(screen)); + 1.0f, 1.0f, + scale, scale); GLASS_CHECK_EXCEPTION(env); } --- old/modules/graphics/src/main/native-glass/mac/GlassView.h 2016-03-30 23:39:58.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/mac/GlassView.h 2016-03-30 23:39:58.000000000 -0700 @@ -45,7 +45,7 @@ // the graphics specifics APIs - (void)begin; - (void)end; -- (void)pushPixels:(void*)pixels withWidth:(GLuint)width withHeight:(GLuint)height withScale:(GLfloat)scale withEnv:(JNIEnv *)env; +- (void)pushPixels:(void*)pixels withWidth:(GLuint)width withHeight:(GLuint)height withScaleX:(GLfloat)scaleX withScaleY:(GLfloat)scaleY withEnv:(JNIEnv *)env; - (GlassViewDelegate*)delegate; - (void)setInputMethodEnabled:(BOOL)enabled; --- old/modules/graphics/src/main/native-glass/mac/GlassView.m 2016-03-30 23:39:59.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/mac/GlassView.m 2016-03-30 23:39:59.000000000 -0700 @@ -659,7 +659,7 @@ * Signature: (JLjava/nio/Buffer;II)V */ JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacView__1uploadPixelsDirect -(JNIEnv *env, jobject jView, jlong jPtr, jobject jBuffer, jint jWidth, jint jHeight, jfloat jScale) +(JNIEnv *env, jobject jView, jlong jPtr, jobject jBuffer, jint jWidth, jint jHeight, jfloat jScaleX, jfloat jScaleY) { LOG("Java_com_sun_glass_ui_mac_MacView__1uploadPixelsDirect"); if (!jPtr) return; @@ -676,7 +676,7 @@ // must be in the middle of begin/end if ((jWidth > 0) && (jHeight > 0)) { - [view pushPixels:pixels withWidth:(GLuint)jWidth withHeight:(GLuint)jHeight withScale:(GLfloat)jScale withEnv:env]; + [view pushPixels:pixels withWidth:(GLuint)jWidth withHeight:(GLuint)jHeight withScaleX:(GLfloat)jScaleX withScaleY:(GLfloat)jScaleY withEnv:env]; } } @@ -686,7 +686,7 @@ * Signature: (J[BIII)V */ JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacView__1uploadPixelsByteArray -(JNIEnv *env, jobject jView, jlong jPtr, jbyteArray jArray, jint jOffset, jint jWidth, jint jHeight, jfloat jScale) +(JNIEnv *env, jobject jView, jlong jPtr, jbyteArray jArray, jint jOffset, jint jWidth, jint jHeight, jfloat jScaleX, jfloat jScaleY) { LOG("Java_com_sun_glass_ui_mac_MacView__1uploadPixelsByteArray"); if (!jPtr) return; @@ -709,7 +709,7 @@ // must be in the middle of begin/end if ((jWidth > 0) && (jHeight > 0)) { - [view pushPixels:pixels withWidth:(GLuint)jWidth withHeight:(GLuint)jHeight withScale:(GLfloat)jScale withEnv:env]; + [view pushPixels:pixels withWidth:(GLuint)jWidth withHeight:(GLuint)jHeight withScaleX:(GLfloat)jScaleX withScaleY:(GLfloat)jScaleY withEnv:env]; } } (*env)->ReleasePrimitiveArrayCritical(env, jArray, data, JNI_ABORT); @@ -721,7 +721,7 @@ * Signature: (J[IIII)V */ JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacView__1uploadPixelsIntArray -(JNIEnv *env, jobject jView, jlong jPtr, jintArray jArray, jint jOffset, jint jWidth, jint jHeight, jfloat jScale) +(JNIEnv *env, jobject jView, jlong jPtr, jintArray jArray, jint jOffset, jint jWidth, jint jHeight, jfloat jScaleX, jfloat jScaleY) { LOG("Java_com_sun_glass_ui_mac_MacView__1uploadPixelsIntArray"); if (!jPtr) return; @@ -744,7 +744,7 @@ // must be in the middle of begin/end if ((jWidth > 0) && (jHeight > 0)) { - [view pushPixels:pixels withWidth:(GLuint)jWidth withHeight:(GLuint)jHeight withScale:(GLfloat)jScale withEnv:env]; + [view pushPixels:pixels withWidth:(GLuint)jWidth withHeight:(GLuint)jHeight withScaleX:(GLfloat)jScaleX withScaleY:(GLfloat)jScaleY withEnv:env]; } } (*env)->ReleasePrimitiveArrayCritical(env, jArray, data, JNI_ABORT); --- old/modules/graphics/src/main/native-glass/mac/GlassView2D.m 2016-03-30 23:40:01.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/mac/GlassView2D.m 2016-03-30 23:40:01.000000000 -0700 @@ -372,7 +372,7 @@ CGContextRestoreGState(cgContext); } -- (void)pushPixels:(void*)pixels withWidth:(GLuint)width withHeight:(GLuint)height withScale:(GLfloat)scale withEnv:(JNIEnv *)env +- (void)pushPixels:(void*)pixels withWidth:(GLuint)width withHeight:(GLuint)height withScaleX:(GLfloat)scalex withScaleY:(GLfloat)scaley withEnv:(JNIEnv *)env { assert([NSGraphicsContext currentContext] != nil); @@ -397,7 +397,7 @@ CGContextTranslateCTM(cgContext, 0, size.height); CGContextScaleCTM(cgContext, 1, -1); CGContextSetBlendMode(cgContext, kCGBlendModeCopy); - CGContextDrawImage(cgContext, CGRectMake(0, 0, width/scale, height/scale), cgImage); + CGContextDrawImage(cgContext, CGRectMake(0, 0, width/scalex, height/scaley), cgImage); } CGContextRestoreGState(cgContext); } --- old/modules/graphics/src/main/native-glass/mac/GlassView3D.m 2016-03-30 23:40:02.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/mac/GlassView3D.m 2016-03-30 23:40:02.000000000 -0700 @@ -633,7 +633,7 @@ [self->_delegate drawRect:dirtyRect]; } -- (void)pushPixels:(void*)pixels withWidth:(GLuint)width withHeight:(GLuint)height withScale:(GLfloat)scale withEnv:(JNIEnv *)env +- (void)pushPixels:(void*)pixels withWidth:(GLuint)width withHeight:(GLuint)height withScaleX:(GLfloat)scalex withScaleY:(GLfloat)scaley withEnv:(JNIEnv *)env { assert(self->_drawCounter > 0); @@ -671,8 +671,8 @@ GLfloat h = self->_textureHeight; NSSize size = [self bounds].size; - size.width *= scale; - size.height *= scale; + size.width *= scalex; + size.height *= scaley; if ((size.width != w) || (size.height != h)) { // This could happen on live resize, clear the FBO to avoid rendering garbage --- old/modules/graphics/src/main/native-glass/mac/GlassWindow.m 2016-03-30 23:40:03.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/mac/GlassWindow.m 2016-03-30 23:40:03.000000000 -0700 @@ -1121,7 +1121,7 @@ * Method: _setBounds * Signature: (JIIZZIIIIFF)V */ -JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setBounds +JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacWindow__1setBounds2 (JNIEnv *env, jobject jWindow, jlong jPtr, jint x, jint y, jboolean xSet, jboolean ySet, jint w, jint h, jint cw, jint ch, jfloat xGravity, jfloat yGravity) --- old/modules/graphics/src/main/native-glass/win/GlassApplication.cpp 2016-03-30 23:40:05.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/win/GlassApplication.cpp 2016-03-30 23:40:04.000000000 -0700 @@ -51,9 +51,6 @@ HHOOK GlassApplication::sm_hMouseLLHook = NULL; jfloat GlassApplication::overrideUIScale = -1.0f; -jfloat GlassApplication::overrideRenderScale = -1.0f; -jfloat GlassApplication::minDPIScale = 1.0f; -jboolean GlassApplication::forceIntegerRenderScale = JNI_TRUE; /* static */ void GlassApplication::SetGlassClassLoader(JNIEnv *env, jobject classLoader) @@ -370,13 +367,9 @@ * Signature: ()V */ JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinApplication_initIDs - (JNIEnv *env, jclass cls, - jfloat overrideUIScale, jfloat overrideRenderScale, jfloat minDPIScale, jboolean forceIntegerRenderScale) + (JNIEnv *env, jclass cls, jfloat overrideUIScale) { GlassApplication::overrideUIScale = overrideUIScale; - GlassApplication::overrideRenderScale = overrideRenderScale; - GlassApplication::minDPIScale = minDPIScale; - GlassApplication::forceIntegerRenderScale = forceIntegerRenderScale; javaIDs.Application.reportExceptionMID = env->GetStaticMethodID(cls, "reportException", "(Ljava/lang/Throwable;)V"); --- old/modules/graphics/src/main/native-glass/win/GlassApplication.h 2016-03-30 23:40:06.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/win/GlassApplication.h 2016-03-30 23:40:05.000000000 -0700 @@ -105,22 +105,15 @@ static ULONG GetAccessibilityCount(); static jfloat overrideUIScale; - static jfloat overrideRenderScale; - static jfloat minDPIScale; - static jboolean forceIntegerRenderScale; - inline static jfloat GetUIScale(UINT dpi) + inline static jboolean IsUIScaleOverridden() { - if (overrideUIScale > 0.0f) return overrideUIScale; - jfloat uiScale = dpi / 96.0f; - if (uiScale < minDPIScale) return 1.0f; - return uiScale; + return (overrideUIScale > 0.0f); } - inline static jfloat getRenderScale(jfloat uiScale) { - if (overrideRenderScale > 0.0f) return overrideRenderScale; - if (forceIntegerRenderScale) return ceil(uiScale); - return uiScale; + inline static jfloat GetUIScale(UINT dpi) + { + return IsUIScaleOverridden() ? overrideUIScale : dpi / 96.0f; } protected: --- old/modules/graphics/src/main/native-glass/win/GlassScreen.cpp 2016-03-30 23:40:07.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/win/GlassScreen.cpp 2016-03-30 23:40:07.000000000 -0700 @@ -48,8 +48,8 @@ RECT fxWork; jboolean primaryScreen; jint colorDepth; - jfloat uiScale; - jfloat renderScale; + jfloat uiScaleX; + jfloat uiScaleY; jint dpiX; jint dpiY; jint anchoredInPass; @@ -190,7 +190,7 @@ mis->primaryScreen = ((mix.dwFlags & MONITORINFOF_PRIMARY) != 0) ? JNI_TRUE : JNI_FALSE; mis->colorDepth = ::GetDeviceCaps(hDC, BITSPIXEL) * ::GetDeviceCaps(hDC, PLANES); UINT resx, resy; - UINT uires; + UINT uiresx, uiresy; if (pGetDPIForMonitor) { // If we can use the GetDPIForMonitor function, then its Effective // value will tell us how much we should scale ourselves based on @@ -212,7 +212,8 @@ resx = ::GetDeviceCaps(hDC, LOGPIXELSX); resy = ::GetDeviceCaps(hDC, LOGPIXELSY); } - uires = resx; + uiresx = resx; + uiresy = resy; res = (*pGetDPIForMonitor)(hMonitor, MDT_Raw_DPI, &resx, &resy); #ifdef DEBUG_DPI fprintf(stderr, "raw DPI X,Y = [0x%08x] %d, %d\n", res, resx, resy); @@ -223,12 +224,13 @@ #ifdef DEBUG_DPI fprintf(stderr, "logpixelsX,Y = %d, %d\n", resx, resy); #endif /* DEBUG_DPI */ - uires = resx; + uiresx = resx; + uiresy = resy; } mis->dpiX = resx; mis->dpiY = resy; - mis->uiScale = GlassApplication::GetUIScale(uires); - mis->renderScale = GlassApplication::getRenderScale(mis->uiScale); + mis->uiScaleX = GlassApplication::GetUIScale(uiresx); + mis->uiScaleY = GlassApplication::GetUIScale(uiresy); ::DeleteDC(hDC); } @@ -279,7 +281,7 @@ jclass screenCls = GetScreenCls(env); if (javaIDs.Screen.init == NULL) { - javaIDs.Screen.init = env->GetMethodID(screenCls, "", "(JIIIIIIIIIIIFF)V"); + javaIDs.Screen.init = env->GetMethodID(screenCls, "", "(JIIIIIIIIIIIIIIIFFFF)V"); ASSERT(javaIDs.Screen.init); if (CheckAndClearException(env)) return NULL; } @@ -293,6 +295,11 @@ pMIS->fxMonitor.right - pMIS->fxMonitor.left, pMIS->fxMonitor.bottom - pMIS->fxMonitor.top, + pMIS->rcMonitor.left, + pMIS->rcMonitor.top, + pMIS->rcMonitor.right - pMIS->rcMonitor.left, + pMIS->rcMonitor.bottom - pMIS->rcMonitor.top, + pMIS->fxWork.left, pMIS->fxWork.top, pMIS->fxWork.right - pMIS->fxWork.left, @@ -301,8 +308,10 @@ pMIS->dpiX, pMIS->dpiY, - pMIS->uiScale, - pMIS->renderScale); + pMIS->uiScaleX, + pMIS->uiScaleY, + pMIS->uiScaleX, + pMIS->uiScaleY); if (CheckAndClearException(env)) return NULL; pMIS->gScreen = env->NewGlobalRef(gScn); return gScn; @@ -390,16 +399,19 @@ jint wrkT = pMIS->rcWork .top - monY; jint wrkR = pMIS->rcWork .right - monX; jint wrkB = pMIS->rcWork .bottom - monY; - jfloat scale = pMIS->uiScale; - if (scale > 1.0f) { - pMIS->dpiX = (jint) floorf((pMIS->dpiX / scale) + 0.5f); - pMIS->dpiY = (jint) floorf((pMIS->dpiY / scale) + 0.5f); - monW = (jint) floorf((monW / scale) + 0.5f); - monH = (jint) floorf((monH / scale) + 0.5f); - wrkL = (jint) floorf((wrkL / scale) + 0.5f); - wrkT = (jint) floorf((wrkT / scale) + 0.5f); - wrkR = (jint) floorf((wrkR / scale) + 0.5f); - wrkB = (jint) floorf((wrkB / scale) + 0.5f); + jfloat scalex = pMIS->uiScaleX; + jfloat scaley = pMIS->uiScaleY; + if (scalex != 1.0f) { + pMIS->dpiX = (jint) floorf((pMIS->dpiX / scalex) + 0.5f); + monW = (jint) floorf((monW / scalex) + 0.5f); + wrkL = (jint) floorf((wrkL / scalex) + 0.5f); + wrkR = (jint) floorf((wrkR / scalex) + 0.5f); + } + if (scaley != 1.0f) { + pMIS->dpiY = (jint) floorf((pMIS->dpiY / scaley) + 0.5f); + monH = (jint) floorf((monH / scaley) + 0.5f); + wrkT = (jint) floorf((wrkT / scaley) + 0.5f); + wrkB = (jint) floorf((wrkB / scaley) + 0.5f); } if (xBefore) fxX -= monW; @@ -439,7 +451,7 @@ int x = before ? pAnchor->fxMonitor.left : pAnchor->fxMonitor.right; int yoff = originOffsetFromRanges(pAnchor->rcMonitor.top, pAnchor->rcMonitor.bottom, pMon->rcMonitor.top, pMon->rcMonitor.bottom, - pAnchor->uiScale, pMon->uiScale); + pAnchor->uiScaleY, pMon->uiScaleY); int y = pAnchor->fxMonitor.top + yoff; anchorTo(pMon, x, before, y, false, pass); } @@ -449,7 +461,7 @@ { int xoff = originOffsetFromRanges(pAnchor->rcMonitor.left, pAnchor->rcMonitor.right, pMon->rcMonitor.left, pMon->rcMonitor.right, - pAnchor->uiScale, pMon->uiScale); + pAnchor->uiScaleX, pMon->uiScaleX); int x = pAnchor->fxMonitor.left + xoff; int y = before ? pAnchor->fxMonitor.top : pAnchor->fxMonitor.bottom; anchorTo(pMon, x, false, y, before, pass); --- old/modules/graphics/src/main/native-glass/win/GlassWindow.cpp 2016-03-30 23:40:08.000000000 -0700 +++ new/modules/graphics/src/main/native-glass/win/GlassWindow.cpp 2016-03-30 23:40:08.000000000 -0700 @@ -647,37 +647,83 @@ } void GlassWindow::HandleDPIEvent(WPARAM wParam, LPARAM lParam) { + if (GlassApplication::IsUIScaleOverridden()) { + return; + } + UINT xDPI = LOWORD(wParam); UINT yDPI = HIWORD(wParam); -// fprintf(stderr, "DPI Changed (=> %d, %d)!\n", yDPI, xDPI); JNIEnv* env = GetEnv(); - jfloat newUIScale = GlassApplication::GetUIScale(xDPI); - jfloat newRenderScale = GlassApplication::getRenderScale(newUIScale); - env->CallVoidMethod(m_grefThis, midNotifyScaleChanged, newUIScale, newRenderScale); + jfloat xScale = xDPI / 96.0f; + jfloat yScale = yDPI / 96.0f; + env->CallVoidMethod(m_grefThis, midNotifyScaleChanged, xScale, yScale, xScale, yScale); CheckAndClearException(env); - LPRECT lprcNewScale = (LPRECT) lParam; -#if 0 - RECT oldBounds, oldClient; + // Windows provides new bounds for the window, but they assume that + // all parts (client and non-client) will be rescaled equally. + // Unfortunately, the basic window decoration support does not scale + // so we need to adjust the new bounds to represent the new intended + // client dimensions padded for the unchanging frame border. + LPRECT lprcNewBounds = (LPRECT) lParam; + RECT oldBounds, oldClient, padding, newClient, newBounds; ::GetWindowRect(GetHWND(), &oldBounds); ::GetClientRect(GetHWND(), &oldClient); + float rescaleX = ((float) (lprcNewBounds->right - lprcNewBounds->left)) / + (oldBounds.right - oldBounds.left); + float rescaleY = ((float) (lprcNewBounds->bottom - lprcNewBounds->top)) / + (oldBounds.bottom - oldBounds.top); + + // First compute the padding between non-client and client for the old + // values for the window. This is the size of the frame border + // decorations. These will remain unchanged after the change in DPI. + padding.left = oldClient.left - oldBounds.left; + padding.top = oldClient.top - oldBounds.top; + padding.right = oldBounds.right - oldClient.right; + padding.bottom = oldBounds.bottom - oldClient.bottom; + + // Next compute the correctly scaled new dimensions for the client + // area, based on the ratio of the old window bounds to the suggested + // new window bounds. + jint newClientW = (jint) ceil((oldClient.right - oldClient.left) * rescaleX); + jint newClientH = (jint) ceil((oldClient.bottom - oldClient.top) * rescaleY); + + // Next compute the new client bounds implied by the values provided by + // the WM event data + newClient.left = lprcNewBounds->left + padding.left; + newClient.top = lprcNewBounds->top + padding.top; + newClient.right = newClient.left + newClientW; + newClient.bottom = newClient.top + newClientH; + + // Finally, compute the new bounds of the window by padding out the + // correctly scaled new client region. + newBounds.left = newClient.left - padding.left; + newBounds.top = newClient.top - padding.top; + newBounds.right = newClient.right + padding.right; + newBounds.bottom = newClient.bottom + padding.bottom; +#if 0 POINT cursor; ::GetCursorPos(&cursor); fprintf(stderr, " @ %d, %d\n", cursor.x, cursor.y); - fprintf(stderr, " (%d, %d, %d, %d) [%d x %d] in (%d, %d, %d, %d) [%d x %d] => (%d, %d, %d, %d) [%d x %d]\n", - oldClient.left, oldClient.top, oldClient.right, oldClient.bottom, + fprintf(stderr, " (%d, %d, %d, %d) [%d x %d] in (%d, %d, %d, %d) [%d x %d]\n", + oldClient.left, oldClient.top, oldClient.right, oldClient.bottom, oldClient.right - oldClient.left, oldClient.bottom - oldClient.top, - oldBounds.left, oldBounds.top, oldBounds.right, oldBounds.bottom, - oldBounds.right - oldBounds.left, oldBounds.bottom - oldBounds.top, - lprcNewScale->left, lprcNewScale->top, lprcNewScale->right, lprcNewScale->bottom, - lprcNewScale->right - lprcNewScale->left, lprcNewScale->bottom - lprcNewScale->top); + oldBounds.left, oldBounds.top, oldBounds.right, oldBounds.bottom, + oldBounds.right - oldBounds.left, oldBounds.bottom - oldBounds.top); + fprintf(stderr, " => (suggested) (%d, %d, %d, %d) [%d x %d]\n", + lprcNewBounds->left, lprcNewBounds->top, lprcNewBounds->right, lprcNewBounds->bottom, + lprcNewBounds->right - lprcNewBounds->left, lprcNewBounds->bottom - lprcNewBounds->top); + fprintf(stderr, " => (recomputed) (%d, %d, %d, %d) [%d x %d] in (%d, %d, %d, %d) [%d x %d]\n", + newClient.left, newClient.top, newClient.right, newClient.bottom, + newClient.right - newClient.left, newClient.bottom - newClient.top, + newBounds.left, newBounds.top, newBounds.right, newBounds.bottom, + newBounds.right - newBounds.left, newBounds.bottom - newBounds.top); #endif ::SetWindowPos(GetHWND(), HWND_TOP, - lprcNewScale->left, - lprcNewScale->top, - lprcNewScale->right - lprcNewScale->left, - lprcNewScale->bottom - lprcNewScale->top, + newBounds.left, + newBounds.top, + newBounds.right - newBounds.left, + newBounds.bottom - newBounds.top, SWP_NOZORDER | SWP_NOACTIVATE); } @@ -1096,7 +1142,7 @@ ASSERT(midNotifyResize); if (env->ExceptionCheck()) return; - midNotifyScaleChanged = env->GetMethodID(cls, "notifyScaleChanged", "(FF)V"); + midNotifyScaleChanged = env->GetMethodID(cls, "notifyScaleChanged", "(FFFF)V"); ASSERT(midNotifyScaleChanged); if (env->ExceptionCheck()) return; --- old/modules/graphics/src/test/java/test/com/sun/javafx/pgstub/StubStage.java 2016-03-30 23:40:09.000000000 -0700 +++ new/modules/graphics/src/test/java/test/com/sun/javafx/pgstub/StubStage.java 2016-03-30 23:40:09.000000000 -0700 @@ -72,6 +72,8 @@ public float y = 12; public float width = 256; public float height = 192; + public float renderScaleX = 1.0f; + public float renderScaleY = 1.0f; public boolean visible; public float opacity; @@ -80,7 +82,8 @@ public void setBounds(float x, float y, boolean xSet, boolean ySet, float width, float height, float contentWidth, float contentHeight, - float xGravity, float yGravity) + float xGravity, float yGravity, + float renderScaleX, float renderScaleY) { numTimesSetSizeAndLocation++; @@ -129,26 +132,38 @@ if (sizeChanged) { notificationSender.changedSize(width, height); } + if (renderScaleX > 0.0) this.renderScaleX = renderScaleX; + if (renderScaleY > 0.0) this.renderScaleY = renderScaleY; } @Override - public float getUIScale() { + public float getPlatformScaleX() { return 1.0f; } @Override - public float getRenderScale() { + public float getPlatformScaleY() { + return 1.0f; + } + + @Override + public float getOutputScaleX() { + return 1.0f; + } + + @Override + public float getOutputScaleY() { return 1.0f; } // Just a helper method public void setSize(float w, float h) { - setBounds(0, 0, false, false, w, h, 0, 0, 0, 0); + setBounds(0, 0, false, false, w, h, 0, 0, 0, 0, 0, 0); } // Just a helper method public void setLocation(float x, float y) { - setBounds(x, y, true, true, 0, 0, 0, 0, 0, 0); + setBounds(x, y, true, true, 0, 0, 0, 0, 0, 0, 0, 0); } @Override @@ -330,6 +345,11 @@ } @Override + public void changedScale(float xScale, float yScale) { + process(listener1 -> listener1.changedScale(xScale, yScale)); + } + + @Override public void changedFocused(final boolean focused, final FocusCause cause) { process(listener1 -> listener1.changedFocused(focused, cause)); @@ -345,6 +365,7 @@ process(listener1 -> listener1.changedMaximized(maximized)); } + @Override public void changedAlwaysOnTop(boolean alwaysOnTop) { process(listener1 -> listener1.changedAlwaysOnTop(alwaysOnTop)); } @@ -413,6 +434,7 @@ } + @Override public void setRTL(boolean b) { } } --- old/modules/graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java 2016-03-30 23:40:10.000000000 -0700 +++ new/modules/graphics/src/test/java/test/com/sun/javafx/pgstub/StubToolkit.java 2016-03-30 23:40:10.000000000 -0700 @@ -519,12 +519,12 @@ } @Override - public float getUIScale(Object obj) { + public float getRecommendedOutputScaleX(Object obj) { return ((ScreenConfiguration) obj).getScale(); } @Override - public float getRenderScale(Object obj) { + public float getRecommendedOutputScaleY(Object obj) { return ((ScreenConfiguration) obj).getScale(); } }; --- old/modules/swing/src/main/java/javafx/embed/swing/JFXPanel.java 2016-03-30 23:40:11.000000000 -0700 +++ new/modules/swing/src/main/java/javafx/embed/swing/JFXPanel.java 2016-03-30 23:40:11.000000000 -0700 @@ -208,11 +208,6 @@ // Initialize FX runtime when the JFXPanel instance is constructed private synchronized static void initFx() { // Note that calling PlatformImpl.startup more than once is OK - AccessController.doPrivileged((PrivilegedAction) () -> { - System.setProperty("glass.win.uiScale", "100%"); - System.setProperty("glass.win.renderScale", "100%"); - return null; - }); PlatformImpl.startup(() -> { // No need to do anything here }); @@ -683,6 +678,9 @@ } if (pixelsIm == null) { createResizePixelBuffer(scaleFactor); + if (pixelsIm == null) { + return; + } } DataBufferInt dataBuf = (DataBufferInt)pixelsIm.getRaster().getDataBuffer(); int[] pixelsData = dataBuf.getData(); @@ -712,7 +710,7 @@ if (scaleFactor != newScaleFactor) { createResizePixelBuffer(newScaleFactor); // The scene will request repaint. - scenePeer.setPixelScaleFactor(newScaleFactor); + scenePeer.setPixelScaleFactors(newScaleFactor, newScaleFactor); scaleFactor = newScaleFactor; } } catch (Throwable th) { @@ -906,7 +904,7 @@ if (pWidth > 0 && pHeight > 0) { scenePeer.setSize(pWidth, pHeight); } - scenePeer.setPixelScaleFactor(scaleFactor); + scenePeer.setPixelScaleFactors(scaleFactor, scaleFactor); invokeOnClientEDT(() -> { dnd = new SwingDnD(JFXPanel.this, scenePeer); --- old/modules/swing/src/main/java/javafx/embed/swing/SwingNode.java 2016-03-30 23:40:12.000000000 -0700 +++ new/modules/swing/src/main/java/javafx/embed/swing/SwingNode.java 2016-03-30 23:40:12.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -279,6 +279,22 @@ private List peerRequests = new ArrayList<>(); + private static float getPlatformScaleX(Window win) { + return WindowHelper.getWindowAccessor().getPlatformScaleX(win); + } + + private static float getPlatformScaleY(Window win) { + return WindowHelper.getWindowAccessor().getPlatformScaleY(win); + } + + private float getPlatformScaleX() { + return getPlatformScaleX(getScene().getWindow()); + } + + private float getPlatformScaleY() { + return getPlatformScaleY(getScene().getWindow()); + } + /* * Called on EDT */ @@ -290,9 +306,10 @@ { Runnable r = () -> { Window win = getScene().getWindow(); - float uiScale = WindowHelper.getWindowAccessor().getUIScale(win); + float uiScaleX = getPlatformScaleX(win); + float uiScaleY = getPlatformScaleY(win); peer.setImageBuffer(IntBuffer.wrap(data), x, y, w, h, - w / uiScale, h / uiScale, linestride, scale); + w / uiScaleX, h / uiScaleY, linestride, scale); }; SwingFXUtils.runOnFxThread(() -> { if (peer != null) { @@ -310,8 +327,9 @@ void setImageBounds(final int x, final int y, final int w, final int h) { Runnable r = () -> { Window win = getScene().getWindow(); - float uiScale = WindowHelper.getWindowAccessor().getUIScale(win); - peer.setImageBounds(x, y, w, h, w / uiScale, h / uiScale); + float uiScaleX = getPlatformScaleX(win); + float uiScaleY = getPlatformScaleY(win); + peer.setImageBounds(x, y, w, h, w / uiScaleX, h / uiScaleY); }; SwingFXUtils.runOnFxThread(() -> { if (peer != null) { @@ -377,8 +395,7 @@ */ @Override public double prefWidth(double height) { - float uiScale = WindowHelper.getWindowAccessor().getUIScale(getScene().getWindow()); - return swingPrefWidth / uiScale; + return swingPrefWidth / getPlatformScaleX(); } /** @@ -389,8 +406,7 @@ */ @Override public double prefHeight(double width) { - float uiScale = WindowHelper.getWindowAccessor().getUIScale(getScene().getWindow()); - return swingPrefHeight / uiScale; + return swingPrefHeight / getPlatformScaleY(); } /** @@ -400,8 +416,7 @@ * @return the maximum width that the node should be resized to during layout */ @Override public double maxWidth(double height) { - float uiScale = WindowHelper.getWindowAccessor().getUIScale(getScene().getWindow()); - return swingMaxWidth / uiScale; + return swingMaxWidth / getPlatformScaleX(); } /** @@ -411,8 +426,7 @@ * @return the maximum height that the node should be resized to during layout */ @Override public double maxHeight(double width) { - float uiScale = WindowHelper.getWindowAccessor().getUIScale(getScene().getWindow()); - return swingMaxHeight / uiScale; + return swingMaxHeight / getPlatformScaleY(); } /** @@ -422,8 +436,7 @@ * @return the minimum width that the node should be resized to during layout */ @Override public double minWidth(double height) { - float uiScale = WindowHelper.getWindowAccessor().getUIScale(getScene().getWindow()); - return swingMinWidth / uiScale; + return swingMinWidth / getPlatformScaleX(); } /** @@ -433,8 +446,7 @@ * @return the minimum height that the node should be resized to during layout */ @Override public double minHeight(double width) { - float uiScale = WindowHelper.getWindowAccessor().getUIScale(getScene().getWindow()); - return swingMinHeight / uiScale; + return swingMinHeight / getPlatformScaleY(); } /** @@ -495,16 +507,23 @@ private void addWindowListeners(final Window window) { window.xProperty().addListener(locationListener); window.yProperty().addListener(locationListener); + window.widthProperty().addListener(locationListener); + window.heightProperty().addListener(locationListener); + window.renderScaleXProperty().addListener(locationListener); window.addEventHandler(FocusUngrabEvent.FOCUS_UNGRAB, ungrabHandler); window.showingProperty().addListener(windowVisibleListener); - this.scale = Math.round(WindowHelper.getWindowAccessor().getRenderScale(window)); + // LW framework should be upgraded to separate X,Y scales... + this.scale = (int) Math.round(window.getRenderScaleX()); setLwFrameScale(this.scale); } private void removeWindowListeners(final Window window) { window.xProperty().removeListener(locationListener); window.yProperty().removeListener(locationListener); + window.widthProperty().removeListener(locationListener); + window.heightProperty().removeListener(locationListener); + window.renderScaleXProperty().removeListener(locationListener); window.removeEventHandler(FocusUngrabEvent.FOCUS_UNGRAB, ungrabHandler); window.showingProperty().removeListener(windowVisibleListener); } @@ -584,20 +603,21 @@ return; } Window w = getScene().getWindow(); - float renderScale = WindowHelper.getWindowAccessor().getRenderScale(w); - float uiScale = WindowHelper.getWindowAccessor().getUIScale(w); - int lwScale = Math.round(renderScale); + float renderScaleX = (float) w.getRenderScaleX(); + float uiScaleX = getPlatformScaleX(w); + float uiScaleY = getPlatformScaleY(w); + int lwScale = Math.round(renderScaleX); boolean sendScale = (this.scale != lwScale); this.scale = lwScale; final Point2D loc = localToScene(0, 0); - final int windowX = (int) (w.getX() * uiScale); - final int windowY = (int) (w.getY() * uiScale); - final int windowW = (int) (w.getWidth() * uiScale); - final int windowH = (int) (w.getHeight() * uiScale); - final int frameX = (int) Math.round((w.getX() + getScene().getX() + loc.getX()) * uiScale); - final int frameY = (int) Math.round((w.getY() + getScene().getY() + loc.getY()) * uiScale); - final int frameW = (int) (fxWidth * uiScale); - final int frameH = (int) (fxHeight * uiScale); + final int windowX = (int) (w.getX() * uiScaleX); + final int windowY = (int) (w.getY() * uiScaleY); + final int windowW = (int) (w.getWidth() * uiScaleX); + final int windowH = (int) (w.getHeight() * uiScaleY); + final int frameX = (int) Math.round((w.getX() + getScene().getX() + loc.getX()) * uiScaleX); + final int frameY = (int) Math.round((w.getY() + getScene().getY() + loc.getY()) * uiScaleY); + final int frameW = (int) (fxWidth * uiScaleX); + final int frameH = (int) (fxHeight * uiScaleY); SwingFXUtils.runOnEDT(() -> { if (lwFrame != null) { @@ -881,11 +901,12 @@ int swingButton = SwingEvents.fxMouseButtonToMouseButton(event); long swingWhen = System.currentTimeMillis(); Window win = getScene().getWindow(); - float uiScale = WindowHelper.getWindowAccessor().getUIScale(win); - int relX = (int) Math.round(event.getX() * uiScale); - int relY = (int) Math.round(event.getY() * uiScale); - int absX = (int) Math.round(event.getScreenX() * uiScale); - int absY = (int) Math.round(event.getScreenY() * uiScale); + float uiScaleX = getPlatformScaleX(win); + float uiScaleY = getPlatformScaleY(win); + int relX = (int) Math.round(event.getX() * uiScaleX); + int relY = (int) Math.round(event.getY() * uiScaleY); + int absX = (int) Math.round(event.getScreenX() * uiScaleX); + int absY = (int) Math.round(event.getScreenY() * uiScaleY); java.awt.event.MouseEvent mouseEvent = new java.awt.event.MouseEvent( frame, swingID, swingWhen, swingModifiers, @@ -929,9 +950,10 @@ wheelRotation = signum; } Window w = getScene().getWindow(); - float uiScale = WindowHelper.getWindowAccessor().getUIScale(w); - int x = (int) Math.round(fxX * uiScale); - int y = (int) Math.round(fxY * uiScale); + float uiScaleX = getPlatformScaleX(w); + float uiScaleY = getPlatformScaleY(w); + int x = (int) Math.round(fxX * uiScaleX); + int y = (int) Math.round(fxY * uiScaleY); MouseWheelEvent mouseWheelEvent = new MouseWheelEvent(source, java.awt.event.MouseEvent.MOUSE_WHEEL, System.currentTimeMillis(), swingModifiers, x, y, 0, 0, --- old/modules/swt/src/main/java/javafx/embed/swt/FXCanvas.java 2016-03-30 23:40:13.000000000 -0700 +++ new/modules/swt/src/main/java/javafx/embed/swt/FXCanvas.java 2016-03-30 23:40:13.000000000 -0700 @@ -517,7 +517,7 @@ if (lastScaleFactor != scaleFactor) { resizePixelBuffer(scaleFactor); lastScaleFactor = scaleFactor; - scenePeer.setPixelScaleFactor((float)scaleFactor); + scenePeer.setPixelScaleFactors((float)scaleFactor, (float)scaleFactor); } // if we can't get the pixels, draw the bits that were there before @@ -1034,7 +1034,7 @@ double scaleFactor = getScaleFactor(); resizePixelBuffer(scaleFactor); lastScaleFactor = scaleFactor; - scenePeer.setPixelScaleFactor((float)scaleFactor); + scenePeer.setPixelScaleFactors((float)scaleFactor, (float)scaleFactor); scenePeer.setDragStartListener((fxDragSource, dragAction) -> { Platform.runLater(() -> { DragSource dragSource = createDragSource(fxDragSource, dragAction); --- old/modules/web/src/main/java/com/sun/javafx/webkit/prism/PrismGraphicsManager.java 2016-03-30 23:40:14.000000000 -0700 +++ new/modules/web/src/main/java/com/sun/javafx/webkit/prism/PrismGraphicsManager.java 2016-03-30 23:40:14.000000000 -0700 @@ -45,9 +45,10 @@ static { float ps = 1f; for (Screen s : Screen.getScreens()) { - ps = Math.max(s.getRenderScale(), ps); + ps = Math.max(s.getRecommendedOutputScaleX(), ps); + ps = Math.max(s.getRecommendedOutputScaleY(), ps); } - highestPixelScale = ps; + highestPixelScale = (float) Math.ceil(ps); pixelScaleTransform = BaseTransform.getScaleInstance(ps, ps); }