diff --git a/src/java.desktop/share/classes/java/awt/Robot.java b/src/java.desktop/share/classes/java/awt/Robot.java index 535fe58a676a6..a7af9903e4f01 100644 --- a/src/java.desktop/share/classes/java/awt/Robot.java +++ b/src/java.desktop/share/classes/java/awt/Robot.java @@ -43,6 +43,9 @@ import sun.awt.image.SunWritableRaster; import sun.java2d.SunGraphicsEnvironment; +import static sun.java2d.SunGraphicsEnvironment.toDeviceSpace; +import static sun.java2d.SunGraphicsEnvironment.toDeviceSpaceAbs; + /** * This class is used to generate native system input events * for the purposes of test automation, self-running demos, and @@ -385,13 +388,9 @@ private static void checkKeycodeArgument(int keycode) { */ public synchronized Color getPixelColor(int x, int y) { checkScreenCaptureAllowed(); - AffineTransform tx = GraphicsEnvironment. - getLocalGraphicsEnvironment().getDefaultScreenDevice(). - getDefaultConfiguration().getDefaultTransform(); - x = (int) (x * tx.getScaleX()); - y = (int) (y * tx.getScaleY()); - Color color = new Color(peer.getRGBPixel(x, y)); - return color; + Point point = peer.useAbsoluteCoordinates() ? toDeviceSpaceAbs(x, y) + : toDeviceSpace(x, y); + return new Color(peer.getRGBPixel(point.x, point.y)); } /** @@ -523,17 +522,16 @@ public synchronized BufferedImage createScreenCapture(Rectangle screenRect) { imageArray[0] = highResolutionImage; } else { - - int sX = (int) Math.floor(screenRect.x * uiScaleX); - int sY = (int) Math.floor(screenRect.y * uiScaleY); - int sWidth = (int) Math.ceil(screenRect.width * uiScaleX); - int sHeight = (int) Math.ceil(screenRect.height * uiScaleY); - int[] temppixels; - Rectangle scaledRect = new Rectangle(sX, sY, sWidth, sHeight); - temppixels = peer.getRGBPixels(scaledRect); - + Rectangle scaledRect; + if (peer.useAbsoluteCoordinates()) { + scaledRect = toDeviceSpaceAbs(gc, screenRect.x, + screenRect.y, screenRect.width, screenRect.height); + } else { + scaledRect = toDeviceSpace(gc, screenRect.x, + screenRect.y, screenRect.width, screenRect.height); + } // HighResolutionImage - pixels = temppixels; + pixels = peer.getRGBPixels(scaledRect); buffer = new DataBufferInt(pixels, pixels.length); raster = Raster.createPackedRaster(buffer, scaledRect.width, scaledRect.height, scaledRect.width, bandmasks, null); diff --git a/src/java.desktop/share/classes/java/awt/peer/RobotPeer.java b/src/java.desktop/share/classes/java/awt/peer/RobotPeer.java index 4c77e19307351..10a901817a204 100644 --- a/src/java.desktop/share/classes/java/awt/peer/RobotPeer.java +++ b/src/java.desktop/share/classes/java/awt/peer/RobotPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, 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 @@ -117,4 +117,14 @@ public interface RobotPeer * @see Robot#createScreenCapture(Rectangle) */ int[] getRGBPixels(Rectangle bounds); + + /** + * Determines if absolute coordinates should be used by this peer. + * + * @return {@code true} if absolute coordinates should be used, + * {@code false} otherwise + */ + default boolean useAbsoluteCoordinates() { + return false; + } } diff --git a/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java b/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java index 0f3f195fb197d..c5ce7ebd3155c 100644 --- a/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java +++ b/src/java.desktop/share/classes/sun/java2d/SunGraphicsEnvironment.java @@ -27,6 +27,7 @@ import java.awt.AWTError; import java.awt.Color; +import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; @@ -349,53 +350,124 @@ public static GraphicsConfiguration getGraphicsConfigurationAtPoint( } /** - * Converts coordinates from the user's space to the device space using - * appropriate device transformation. + * Returns the bounds of the graphics configuration in device space. + * + * @param config the graphics configuration which bounds are requested + * @return the bounds of the area covered by this + * {@code GraphicsConfiguration} in device space (pixels) + */ + public static Rectangle getGCDeviceBounds(GraphicsConfiguration config) { + AffineTransform tx = config.getDefaultTransform(); + Rectangle bounds = config.getBounds(); + bounds.width *= tx.getScaleX(); + bounds.height *= tx.getScaleY(); + return bounds; + } + + /** + * Converts the size (w, h) from the device space to the user's space using + * passed graphics configuration. + * + * @param gc the graphics configuration to be used for transformation + * @param w the width in the device space + * @param h the height in the device space + * @return the size in the user's space + */ + public static Dimension toUserSpace(GraphicsConfiguration gc, + int w, int h) { + AffineTransform tx = gc.getDefaultTransform(); + return new Dimension( + Region.clipRound(w / tx.getScaleX()), + Region.clipRound(h / tx.getScaleY()) + ); + } + + /** + * Converts absolute coordinates from the user's space to the device space + * using appropriate device transformation. * - * @param x coordinate in the user space - * @param y coordinate in the user space - * @return the point which uses device space(pixels) + * @param x absolute coordinate in the user's space + * @param y absolute coordinate in the user's space + * @return the point which uses device space (pixels) */ - public static Point convertToDeviceSpace(double x, double y) { + public static Point toDeviceSpaceAbs(int x, int y) { GraphicsConfiguration gc = getLocalGraphicsEnvironment() - .getDefaultScreenDevice().getDefaultConfiguration(); + .getDefaultScreenDevice().getDefaultConfiguration(); gc = getGraphicsConfigurationAtPoint(gc, x, y); + return toDeviceSpaceAbs(gc, x, y, 0, 0).getLocation(); + } + /** + * Converts the rectangle from the user's space to the device space using + * appropriate device transformation. + * + * @param rect the rectangle in the user's space + * @return the rectangle which uses device space (pixels) + */ + public static Rectangle toDeviceSpaceAbs(Rectangle rect) { + GraphicsConfiguration gc = getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + gc = getGraphicsConfigurationAtPoint(gc, rect.x, rect.y); + return toDeviceSpaceAbs(gc, rect.x, rect.y, rect.width, rect.height); + } + + /** + * Converts absolute coordinates (x, y) and the size (w, h) from the user's + * space to the device space using passed graphics configuration. + * + * @param gc the graphics configuration to be used for transformation + * @param x absolute coordinate in the user's space + * @param y absolute coordinate in the user's space + * @param w the width in the user's space + * @param h the height in the user's space + * @return the rectangle which uses device space (pixels) + */ + public static Rectangle toDeviceSpaceAbs(GraphicsConfiguration gc, + int x, int y, int w, int h) { AffineTransform tx = gc.getDefaultTransform(); - x = Region.clipRound(x * tx.getScaleX()); - y = Region.clipRound(y * tx.getScaleY()); - return new Point((int) x, (int) y); + Rectangle screen = gc.getBounds(); + return new Rectangle( + screen.x + Region.clipRound((x - screen.x) * tx.getScaleX()), + screen.y + Region.clipRound((y - screen.y) * tx.getScaleY()), + Region.clipRound(w * tx.getScaleX()), + Region.clipRound(h * tx.getScaleY()) + ); } /** - * Converts bounds from the user's space to the device space using + * Converts coordinates from the user's space to the device space using * appropriate device transformation. * - * @param bounds the rectangle in the user space - * @return the rectangle which uses device space(pixels) + * @param x coordinate in the user's space + * @param y coordinate in the user's space + * @return the point which uses device space (pixels) */ - public static Rectangle convertToDeviceSpace(Rectangle bounds) { + public static Point toDeviceSpace(int x, int y) { GraphicsConfiguration gc = getLocalGraphicsEnvironment() .getDefaultScreenDevice().getDefaultConfiguration(); - gc = getGraphicsConfigurationAtPoint(gc, bounds.x, bounds.y); - return convertToDeviceSpace(gc, bounds); + gc = getGraphicsConfigurationAtPoint(gc, x, y); + return toDeviceSpace(gc, x, y, 0, 0).getLocation(); } /** - * Converts bounds from the user's space to the device space using - * appropriate device transformation of the passed graphics configuration. + * Converts coordinates (x, y) and the size (w, h) from the user's + * space to the device space using passed graphics configuration. * - * @param bounds the rectangle in the user space - * @return the rectangle which uses device space(pixels) + * @param gc the graphics configuration to be used for transformation + * @param x coordinate in the user's space + * @param y coordinate in the user's space + * @param w the width in the user's space + * @param h the height in the user's space + * @return the rectangle which uses device space (pixels) */ - public static Rectangle convertToDeviceSpace(GraphicsConfiguration gc, - Rectangle bounds) { + public static Rectangle toDeviceSpace(GraphicsConfiguration gc, + int x, int y, int w, int h) { AffineTransform tx = gc.getDefaultTransform(); return new Rectangle( - Region.clipRound(bounds.x * tx.getScaleX()), - Region.clipRound(bounds.y * tx.getScaleY()), - Region.clipRound(bounds.width * tx.getScaleX()), - Region.clipRound(bounds.height * tx.getScaleY()) + Region.clipRound(x * tx.getScaleX()), + Region.clipRound(y * tx.getScaleY()), + Region.clipRound(w * tx.getScaleX()), + Region.clipRound(h * tx.getScaleY()) ); } } diff --git a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java index b4962f2a5d735..52a3678606433 100644 --- a/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java +++ b/src/java.desktop/windows/classes/sun/awt/Win32GraphicsDevice.java @@ -467,7 +467,7 @@ public synchronized void setDisplayMode(DisplayMode dm) { // display mode Rectangle screenBounds = getDefaultConfiguration().getBounds(); w.setBounds(screenBounds.x, screenBounds.y, - dm.getWidth(), dm.getHeight()); + screenBounds.width, screenBounds.height); // Note: no call to replaceSurfaceData is required here since // replacement will be caused by an upcoming display change event } else { diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java index d8114aed4535c..c07d116abfbcb 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java @@ -533,7 +533,11 @@ public void run() { @Override public boolean updateGraphicsData(GraphicsConfiguration gc) { + var old = getGraphicsConfiguration().getDefaultTransform(); winGraphicsConfig = (Win32GraphicsConfig)gc; + if (gc != null && !old.equals(gc.getDefaultTransform())) { + syncBounds(); // the bounds of the peer depend on the DPI + } try { replaceSurfaceData(); } catch (InvalidPipeException e) { @@ -542,6 +546,14 @@ public boolean updateGraphicsData(GraphicsConfiguration gc) { return false; } + /** + * Make sure that the native peer's coordinates are in sync with the target. + */ + void syncBounds() { + Rectangle r = ((Component) target).getBounds(); + setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS); + } + //This will return null for Components not yet added to a Container @Override public ColorModel getColorModel() { diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WDialogPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WDialogPeer.java index ea4fc4aaa41ac..930064d598120 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WDialogPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WDialogPeer.java @@ -36,6 +36,8 @@ import sun.awt.AWTAccessor; import sun.awt.im.InputMethodManager; +import static sun.java2d.SunGraphicsEnvironment.toUserSpace; + final class WDialogPeer extends WWindowPeer implements DialogPeer { // Toolkit & peer internals @@ -117,8 +119,8 @@ public Dimension getMinimumSize() { if (((Dialog)target).isUndecorated()) { return super.getMinimumSize(); } - return new Dimension(scaleDownX(getSysMinWidth()), - scaleDownY(getSysMinHeight())); + return toUserSpace(getGraphicsConfiguration(), + getSysMinWidth(), getSysMinHeight()); } @Override diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java index eaa830fc8af64..8671f25f308a4 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WFramePeer.java @@ -38,7 +38,9 @@ import sun.awt.im.InputMethodManager; import sun.security.action.GetPropertyAction; -import static sun.java2d.SunGraphicsEnvironment.convertToDeviceSpace; +import static sun.java2d.SunGraphicsEnvironment.getGCDeviceBounds; +import static sun.java2d.SunGraphicsEnvironment.toDeviceSpaceAbs; +import static sun.java2d.SunGraphicsEnvironment.toUserSpace; class WFramePeer extends WWindowPeer implements FramePeer { @@ -97,10 +99,9 @@ public final void setMaximizedBounds(Rectangle b) { */ private Rectangle adjustMaximizedBounds(Rectangle bounds) { // All calculations should be done in the device space - bounds = convertToDeviceSpace(bounds); - + bounds = toDeviceSpaceAbs(bounds); GraphicsConfiguration gc = getGraphicsConfiguration(); - Rectangle currentDevBounds = convertToDeviceSpace(gc, gc.getBounds()); + Rectangle currentDevBounds = getGCDeviceBounds(gc); // Prepare data for WM_GETMINMAXINFO message. // ptMaxPosition should be in coordinate system of the current monitor, // not the main monitor, or monitor on which we maximize the window. @@ -148,13 +149,13 @@ public void reshape(int x, int y, int width, int height) { @Override public final Dimension getMinimumSize() { + GraphicsConfiguration gc = getGraphicsConfiguration(); Dimension d = new Dimension(); if (!((Frame)target).isUndecorated()) { - d.setSize(scaleDownX(getSysMinWidth()), - scaleDownY(getSysMinHeight())); + d.setSize(toUserSpace(gc, getSysMinWidth(), getSysMinHeight())); } - if (((Frame)target).getMenuBar() != null) { - d.height += scaleDownY(getSysMenuHeight()); + if (((Frame) target).getMenuBar() != null) { + d.height += toUserSpace(gc, 0, getSysMenuHeight()).height; } return d; } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WRobotPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WRobotPeer.java index 4d17500e079a1..ad924dd6e1f5e 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WRobotPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WRobotPeer.java @@ -29,14 +29,14 @@ import java.awt.Rectangle; import java.awt.peer.RobotPeer; -import sun.java2d.SunGraphicsEnvironment; +import static sun.java2d.SunGraphicsEnvironment.toDeviceSpaceAbs; final class WRobotPeer implements RobotPeer { public native void mouseMoveImpl(int x, int y); @Override public void mouseMove(int x, int y) { - Point point = SunGraphicsEnvironment.convertToDeviceSpace(x, y); + Point point = toDeviceSpaceAbs(x, y); mouseMoveImpl(point.x, point.y); } @Override @@ -64,5 +64,10 @@ public int getRGBPixel(int x, int y) { return pixelArray; } + @Override + public boolean useAbsoluteCoordinates() { + return true; + } + private native void getRGBPixels(int x, int y, int width, int height, int[] pixelArray); } diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java index 5db663c6f7f53..6c3d059457de3 100644 --- a/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java +++ b/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java @@ -63,10 +63,11 @@ import sun.awt.Win32GraphicsConfig; import sun.awt.Win32GraphicsDevice; import sun.awt.Win32GraphicsEnvironment; -import sun.java2d.SunGraphicsEnvironment; import sun.java2d.pipe.Region; import sun.util.logging.PlatformLogger; +import static sun.java2d.SunGraphicsEnvironment.toUserSpace; + public class WWindowPeer extends WPanelPeer implements WindowPeer, DisplayChangedListener { @@ -108,8 +109,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer, * WindowStateEvent is posted to the EventQueue. */ private WindowListener windowListener; - private float scaleX; - private float scaleY; /** * Initialize JNI field IDs @@ -222,8 +221,6 @@ void initialize() { GraphicsConfiguration gc = getGraphicsConfiguration(); Win32GraphicsDevice gd = (Win32GraphicsDevice) gc.getDevice(); gd.addDisplayChangedListener(this); - scaleX = gd.getDefaultScaleX(); - scaleY = gd.getDefaultScaleY(); initActiveWindowsTracking((Window)target); @@ -310,6 +307,12 @@ public void show() { } } + @Override + final void syncBounds() { + // Windows will take care of the top-level window/frame/dialog, and + // update the location/size when DPI changes. + } + // Synchronize the insets members (here & in helper) with actual window // state. native void updateInsets(Insets i); @@ -438,9 +441,10 @@ public void updateMinimumSize() { minimumSize = ((Component)target).getMinimumSize(); } if (minimumSize != null) { - int w = Math.max(minimumSize.width, scaleDownX(getSysMinWidth())); - int h = Math.max(minimumSize.height, scaleDownY(getSysMinHeight())); - setMinSize(w, h); + Dimension sysMin = toUserSpace(getGraphicsConfiguration(), + getSysMinWidth(), getSysMinHeight()); + setMinSize(Math.max(minimumSize.width, sysMin.width), + Math.max(minimumSize.height, sysMin.height)); } else { setMinSize(0, 0); } @@ -598,21 +602,6 @@ public void updateGC() { AWTAccessor.getComponentAccessor(). setGraphicsConfiguration((Component)target, winGraphicsConfig); - - checkDPIChange(oldDev, newDev); - } - - private void checkDPIChange(Win32GraphicsDevice oldDev, - Win32GraphicsDevice newDev) { - float newScaleX = newDev.getDefaultScaleX(); - float newScaleY = newDev.getDefaultScaleY(); - - if (scaleX != newScaleX || scaleY != newScaleY) { - windowDPIChange(oldDev.getScreen(), scaleX, scaleY, - newDev.getScreen(), newScaleX, newScaleY); - scaleX = newScaleX; - scaleY = newScaleY; - } } /** @@ -666,77 +655,9 @@ boolean isTargetUndecorated() { return true; } - // These are the peer bounds. They get updated at: - // 1. the WWindowPeer.setBounds() method. - // 2. the native code (on WM_SIZE/WM_MOVE) - private volatile int sysX = 0; - private volatile int sysY = 0; - private volatile int sysW = 0; - private volatile int sysH = 0; - @Override public native void repositionSecurityWarning(); - @Override - public void setBounds(int x, int y, int width, int height, int op) { - sysX = x; - sysY = y; - sysW = width; - sysH = height; - - int cx = x + width / 2; - int cy = y + height / 2; - GraphicsConfiguration current = getGraphicsConfiguration(); - GraphicsConfiguration other = SunGraphicsEnvironment - .getGraphicsConfigurationAtPoint(current, cx, cy); - if (!current.equals(other)) { - AffineTransform tx = other.getDefaultTransform(); - double otherScaleX = tx.getScaleX(); - double otherScaleY = tx.getScaleY(); - initScales(); - if (scaleX != otherScaleX || scaleY != otherScaleY) { - x = (int) Math.floor(x * otherScaleX / scaleX); - y = (int) Math.floor(y * otherScaleY / scaleY); - } - } - - super.setBounds(x, y, width, height, op); - } - - private void initScales() { - - if (scaleX >= 1 && scaleY >= 1) { - return; - } - - GraphicsConfiguration gc = getGraphicsConfiguration(); - if (gc instanceof Win32GraphicsConfig) { - Win32GraphicsDevice gd = ((Win32GraphicsConfig) gc).getDevice(); - scaleX = gd.getDefaultScaleX(); - scaleY = gd.getDefaultScaleY(); - } else { - AffineTransform tx = gc.getDefaultTransform(); - scaleX = (float) tx.getScaleX(); - scaleY = (float) tx.getScaleY(); - } - } - - final int scaleUpX(int x) { - return Region.clipRound(x * scaleX); - } - - final int scaleUpY(int y) { - return Region.clipRound(y * scaleY); - } - - final int scaleDownX(int x) { - return Region.clipRound(x / scaleX); - } - - final int scaleDownY(int y) { - return Region.clipRound(y / scaleY); - } - @Override public void print(Graphics g) { // We assume we print the whole frame, @@ -905,9 +826,6 @@ private void updateWindow(boolean repaint) { } } - native void windowDPIChange(int prevScreen, float prevScaleX, float prevScaleY, - int newScreen, float newScaleX, float newScaleY); - /* * The method maps the list of the active windows to the window's AppContext, * then the method registers ActiveWindowListener, GuiDisposedListener listeners; diff --git a/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp b/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp index 37fbc914519ef..560764e8b28f0 100644 --- a/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp +++ b/src/java.desktop/windows/native/libawt/windows/MouseInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, 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 @@ -106,8 +106,8 @@ Java_sun_awt_windows_WMouseInfoPeer_fillPointWithCoords(JNIEnv *env, jclass cls, yID = env->GetFieldID(pointClass, "y", "I"); CHECK_NULL_RETURN(yID, (jint)0); - int x = (device == NULL) ? pt.x : device->ScaleDownX(pt.x); - int y = (device == NULL) ? pt.y : device->ScaleDownY(pt.y); + int x = (device == NULL) ? pt.x : device->ScaleDownAbsX(pt.x); + int y = (device == NULL) ? pt.y : device->ScaleDownAbsY(pt.y); env->SetIntField(point, xID, x); env->SetIntField(point, yID, y); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index 9e15a77514a15..1ed97ba94d241 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -603,7 +603,7 @@ AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title, /* * Fix for 4046446. */ - SetWindowPos(GetHWnd(), 0, x, y, w, h, SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOACTIVATE); + Reshape(x, y, w, h); /* Set default colors. */ m_colorForeground = colorForeground; @@ -1087,6 +1087,7 @@ void SpyWinMessage(HWND hwnd, UINT message, LPCTSTR szComment) { WIN_MSG(WM_DESTROY) WIN_MSG(WM_MOVE) WIN_MSG(WM_SIZE) + WIN_MSG(WM_DPICHANGED) WIN_MSG(WM_ACTIVATE) WIN_MSG(WM_SETFOCUS) WIN_MSG(WM_KILLFOCUS) @@ -1505,9 +1506,9 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) case WM_SIZE: { RECT r; - // fix 4128317 : use GetClientRect for full 32-bit int precision and + // fix 4128317 : use GetWindowRect for full 32-bit int precision and // to avoid negative client area dimensions overflowing 16-bit params - robi - ::GetClientRect( GetHWnd(), &r ); + ::GetWindowRect(GetHWnd(), &r); mr = WmSize(static_cast(wParam), r.right - r.left, r.bottom - r.top); //mr = WmSize(wParam, LOWORD(lParam), HIWORD(lParam)); SetCompositionWindow(r); @@ -3888,8 +3889,8 @@ void AwtComponent::OpenCandidateWindow(int x, int y) } HWND hTop = GetTopLevelParentForWindow(hWnd); ::ClientToScreen(hTop, &p); - int sx = ScaleUpX(x) - p.x; - int sy = ScaleUpY(y) - p.y; + int sx = ScaleUpAbsX(x) - p.x; + int sy = ScaleUpAbsY(y) - p.y; if (!m_bitsCandType) { SetCandidateWindow(m_bitsCandType, sx, sy); return; @@ -4767,34 +4768,71 @@ void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha) } } +int AwtComponent::GetScreenImOn() { + HWND hWindow = GetAncestor(GetHWnd(), GA_ROOT); + AwtComponent *comp = AwtComponent::GetComponent(hWindow); + if (comp && comp->IsTopLevel()) { + return comp->GetScreenImOn(); + } + return AwtWin32GraphicsDevice::DeviceIndexForWindow(hWindow); +} + int AwtComponent::ScaleUpX(int x) { - int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); + int screen = GetScreenImOn(); Devices::InstanceAccess devices; AwtWin32GraphicsDevice* device = devices->GetDevice(screen); return device == NULL ? x : device->ScaleUpX(x); } +int AwtComponent::ScaleUpAbsX(int x) { + int screen = GetScreenImOn(); + Devices::InstanceAccess devices; + AwtWin32GraphicsDevice* device = devices->GetDevice(screen); + return device == NULL ? x : device->ScaleUpAbsX(x); +} + int AwtComponent::ScaleUpY(int y) { - int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); + int screen = GetScreenImOn(); Devices::InstanceAccess devices; AwtWin32GraphicsDevice* device = devices->GetDevice(screen); return device == NULL ? y : device->ScaleUpY(y); } +int AwtComponent::ScaleUpAbsY(int y) { + int screen = GetScreenImOn(); + Devices::InstanceAccess devices; + AwtWin32GraphicsDevice* device = devices->GetDevice(screen); + return device == NULL ? y : device->ScaleUpAbsY(y); +} + int AwtComponent::ScaleDownX(int x) { - int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); + int screen = GetScreenImOn(); Devices::InstanceAccess devices; AwtWin32GraphicsDevice* device = devices->GetDevice(screen); return device == NULL ? x : device->ScaleDownX(x); } +int AwtComponent::ScaleDownAbsX(int x) { + int screen = GetScreenImOn(); + Devices::InstanceAccess devices; + AwtWin32GraphicsDevice* device = devices->GetDevice(screen); + return device == NULL ? x : device->ScaleDownAbsX(x); +} + int AwtComponent::ScaleDownY(int y) { - int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(GetHWnd()); + int screen = GetScreenImOn(); Devices::InstanceAccess devices; AwtWin32GraphicsDevice* device = devices->GetDevice(screen); return device == NULL ? y : device->ScaleDownY(y); } +int AwtComponent::ScaleDownAbsY(int y) { + int screen = GetScreenImOn(); + Devices::InstanceAccess devices; + AwtWin32GraphicsDevice* device = devices->GetDevice(screen); + return device == NULL ? y : device->ScaleDownAbsY(y); +} + jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -5090,7 +5128,7 @@ void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y, id, when, modifiers, ScaleDownX(x + insets.left), ScaleDownY(y + insets.top), - ScaleDownX(xAbs), ScaleDownY(yAbs), + ScaleDownAbsX(xAbs), ScaleDownAbsY(yAbs), clickCount, popupTrigger, button); if (safe_ExceptionOccurred(env)) { @@ -5163,8 +5201,8 @@ AwtComponent::SendMouseWheelEvent(jint id, jlong when, jint x, jint y, id, when, modifiers, ScaleDownX(x + insets.left), ScaleDownY(y + insets.top), - ScaleDownX(xAbs), - ScaleDownY(yAbs), + ScaleDownAbsX(xAbs), + ScaleDownAbsY(yAbs), clickCount, popupTrigger, scrollType, scrollAmount, roundedWheelRotation, preciseWheelRotation); @@ -5674,8 +5712,8 @@ jobject AwtComponent::_GetLocationOnScreen(void *param) RECT rect; VERIFY(::GetWindowRect(p->GetHWnd(),&rect)); result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V", - p->ScaleDownX(rect.left), - p->ScaleDownY(rect.top)); + p->ScaleDownAbsX(rect.left), + p->ScaleDownAbsY(rect.top)); } ret: env->DeleteGlobalRef(self); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.h b/src/java.desktop/windows/native/libawt/windows/awt_Component.h index 1e3e076927304..d950e78abda34 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Component.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.h @@ -275,6 +275,7 @@ class AwtComponent : public AwtObject { /* * methods on this component */ + virtual int GetScreenImOn(); virtual void Show(); virtual void Hide(); virtual void Reshape(int x, int y, int w, int h); @@ -755,9 +756,13 @@ class AwtComponent : public AwtObject { virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha); int ScaleUpX(int x); + int ScaleUpAbsX(int x); int ScaleUpY(int y); + int ScaleUpAbsY(int y); int ScaleDownX(int x); + int ScaleDownAbsX(int x); int ScaleDownY(int y); + int ScaleDownAbsY(int y); private: /* A bitmask keeps the button's numbers as MK_LBUTTON, MK_MBUTTON, MK_RBUTTON diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Cursor.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Cursor.cpp index 642c9e9b14c6b..4a1a4c08131aa 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Cursor.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Cursor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, 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 @@ -475,8 +475,8 @@ Java_sun_awt_windows_WGlobalCursorManager_getCursorPos(JNIEnv *env, int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(monitor); Devices::InstanceAccess devices; AwtWin32GraphicsDevice *device = devices->GetDevice(screen); - int x = (device == NULL) ? p.x : device->ScaleDownX(p.x); - int y = (device == NULL) ? p.y : device->ScaleDownY(p.y); + int x = (device == NULL) ? p.x : device->ScaleDownAbsX(p.x); + int y = (device == NULL) ? p.y : device->ScaleDownAbsY(p.y); env->SetIntField(point, AwtCursor::pointXID, x); env->SetIntField(point, AwtCursor::pointYID, y); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp index 390b9250abafa..0f9fb662bbf5c 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_DnDDS.cpp @@ -1174,14 +1174,14 @@ HRESULT __stdcall AwtDragSource::GetProcessId(FORMATETC __RPC_FAR *pFormatEtc, S return S_OK; } -static void ScaleDown(POINT &pt) { +static void ScaleDownAbs(POINT &pt) { HMONITOR monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(monitor); Devices::InstanceAccess devices; AwtWin32GraphicsDevice *device = devices->GetDevice(screen); if (device) { - pt.x = device->ScaleDownX(pt.x); - pt.y = device->ScaleDownY(pt.y); + pt.x = device->ScaleDownAbsX(pt.x); + pt.y = device->ScaleDownAbsY(pt.y); } } @@ -1190,7 +1190,7 @@ DECLARE_JAVA_CLASS(dSCClazz, "sun/awt/windows/WDragSourceContextPeer") void AwtDragSource::call_dSCenter(JNIEnv* env, jobject self, jint targetActions, jint modifiers, POINT pt) { - ScaleDown(pt); + ScaleDownAbs(pt); DECLARE_VOID_JAVA_METHOD(dSCenter, dSCClazz, "dragEnter", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCenter, targetActions, modifiers, pt.x, pt.y); @@ -1203,7 +1203,7 @@ AwtDragSource::call_dSCenter(JNIEnv* env, jobject self, jint targetActions, void AwtDragSource::call_dSCmotion(JNIEnv* env, jobject self, jint targetActions, jint modifiers, POINT pt) { - ScaleDown(pt); + ScaleDownAbs(pt); DECLARE_VOID_JAVA_METHOD(dSCmotion, dSCClazz, "dragMotion", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCmotion, targetActions, modifiers, pt.x, pt.y); @@ -1216,7 +1216,7 @@ AwtDragSource::call_dSCmotion(JNIEnv* env, jobject self, jint targetActions, void AwtDragSource::call_dSCchanged(JNIEnv* env, jobject self, jint targetActions, jint modifiers, POINT pt) { - ScaleDown(pt); + ScaleDownAbs(pt); DECLARE_VOID_JAVA_METHOD(dSCchanged, dSCClazz, "operationChanged", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); @@ -1229,7 +1229,7 @@ AwtDragSource::call_dSCchanged(JNIEnv* env, jobject self, jint targetActions, void AwtDragSource::call_dSCexit(JNIEnv* env, jobject self, POINT pt) { - ScaleDown(pt); + ScaleDownAbs(pt); DECLARE_VOID_JAVA_METHOD(dSCexit, dSCClazz, "dragExit", "(II)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCexit, pt.x, pt.y); @@ -1242,7 +1242,7 @@ AwtDragSource::call_dSCexit(JNIEnv* env, jobject self, POINT pt) { void AwtDragSource::call_dSCddfinished(JNIEnv* env, jobject self, jboolean success, jint operations, POINT pt) { - ScaleDown(pt); + ScaleDownAbs(pt); DECLARE_VOID_JAVA_METHOD(dSCddfinished, dSCClazz, "dragDropFinished", "(ZIII)V"); DASSERT(!JNU_IsNull(env, self)); env->CallVoidMethod(self, dSCddfinished, success, operations, pt.x, pt.y); @@ -1255,7 +1255,7 @@ AwtDragSource::call_dSCddfinished(JNIEnv* env, jobject self, jboolean success, void AwtDragSource::call_dSCmouseMoved(JNIEnv* env, jobject self, jint targetActions, jint modifiers, POINT pt) { - ScaleDown(pt); + ScaleDownAbs(pt); DECLARE_VOID_JAVA_METHOD(dSCmouseMoved, dSCClazz, "dragMouseMoved", "(IIII)V"); DASSERT(!JNU_IsNull(env, self)); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_FileDialog.cpp b/src/java.desktop/windows/native/libawt/windows/awt_FileDialog.cpp index 119b2c3680c2b..e8128372ceb0a 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_FileDialog.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_FileDialog.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, 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 @@ -631,18 +631,18 @@ Java_sun_awt_windows_WFileDialogPeer_toBack(JNIEnv *env, jobject peer) CATCH_BAD_ALLOC; } -int ScaleDownX(int x, HWND hwnd) { +int ScaleDownAbsX(int x, HWND hwnd) { int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(hwnd); Devices::InstanceAccess devices; AwtWin32GraphicsDevice* device = devices->GetDevice(screen); - return device == NULL ? x : device->ScaleDownX(x); + return device == NULL ? x : device->ScaleDownAbsX(x); } -int ScaleDownY(int y, HWND hwnd) { +int ScaleDownAbsY(int y, HWND hwnd) { int screen = AwtWin32GraphicsDevice::DeviceIndexForWindow(hwnd); Devices::InstanceAccess devices; AwtWin32GraphicsDevice* device = devices->GetDevice(screen); - return device == NULL ? y : device->ScaleDownY(y); + return device == NULL ? y : device->ScaleDownAbsY(y); } jobject AwtFileDialog::_GetLocationOnScreen(void *param) @@ -657,7 +657,8 @@ jobject AwtFileDialog::_GetLocationOnScreen(void *param) RECT rect; VERIFY(::GetWindowRect(hwnd, &rect)); result = JNU_NewObjectByName(env, "java/awt/Point", "(II)V", - ScaleDownX(rect.left, hwnd), ScaleDownY(rect.top, hwnd)); + ScaleDownAbsX(rect.left, hwnd), + ScaleDownAbsY(rect.top, hwnd)); } if (result != NULL) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp index 8f2fcd84f6f5b..d8873b6bec291 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp @@ -328,17 +328,13 @@ AwtFrame* AwtFrame::Create(jobject self, jobject parent) frame->CreateHWnd(env, L"", style, exStyle, - 0, 0, 0, 0, + x, y, width, height, hwndParent, NULL, ::GetSysColor(COLOR_WINDOWTEXT), ::GetSysColor(COLOR_WINDOWFRAME), self); - /* - * Reshape here instead of during create, so that a - * WM_NCCALCSIZE is sent. - */ - frame->Reshape(x, y, width, height); + frame->RecalcNonClient(); } } } catch (...) { diff --git a/src/java.desktop/windows/native/libawt/windows/awt_List.cpp b/src/java.desktop/windows/native/libawt/windows/awt_List.cpp index 69484f024d799..a04f6182a5b5f 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_List.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_List.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, 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 @@ -288,14 +288,17 @@ void AwtList::SetMultiSelect(BOOL ms) { UnsubclassHWND(); AwtToolkit::DestroyComponentHWND(m_hwnd); - CreateHWnd(env, L"", style, exStyle, - rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + CreateHWnd(env, L"", style, exStyle, 0, 0, 0, 0, parentHWnd, NULL, ::GetSysColor(COLOR_WINDOWTEXT), ::GetSysColor(COLOR_WINDOW), peer); + SetWindowPos(GetHWnd(), 0, + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, + SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOACTIVATE); + SendListMessage(WM_SETFONT, (WPARAM)font, (LPARAM)FALSE); SendListMessage(LB_SETITEMHEIGHT, 0, MAKELPARAM(itemHeight, 0)); SendListMessage(LB_RESETCONTENT); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsConfig.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsConfig.cpp index 7d13fbe2d87e7..463c1fdee10db 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsConfig.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsConfig.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, 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 @@ -99,16 +99,12 @@ JNIEXPORT jobject JNICALL AwtWin32GraphicsDevice *device = devices->GetDevice(screen); if (TRUE == MonitorBounds(AwtWin32GraphicsDevice::GetMonitor(screen), &rRW)) { - - int x = (device == NULL) ? rRW.left : device->ScaleDownX(rRW.left); - int y = (device == NULL) ? rRW.top : device->ScaleDownY(rRW.top); int w = (device == NULL) ? rRW.right - rRW.left : device->ScaleDownX(rRW.right - rRW.left); int h = (device == NULL) ? rRW.bottom - rRW.top : device->ScaleDownY(rRW.bottom - rRW.top); - bounds = env->NewObject(clazz, mid, x, y, w, h); - + bounds = env->NewObject(clazz, mid, rRW.left, rRW.top, w, h); } else { // 4910760 - don't return a null bounds, return the bounds of the diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp index 2b6af9d8f2cac..79e7b9d105016 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp @@ -77,6 +77,7 @@ AwtWin32GraphicsDevice::AwtWin32GraphicsDevice(int screen, this->devicesArray = arr; this->scaleX = 1; this->scaleY = 1; + disableScaleAutoRefresh = FALSE; javaDevice = NULL; colorData = new ImgColorData; colorData->grayscale = GS_NOTGRAY; @@ -633,21 +634,45 @@ int AwtWin32GraphicsDevice::ScaleUpX(int x) return ClipRound(x * scaleX); } +int AwtWin32GraphicsDevice::ScaleUpAbsX(int x) +{ + LONG screen = pMonitorInfo->rcMonitor.left; + return screen + ClipRound((x - screen) * scaleX); +} + int AwtWin32GraphicsDevice::ScaleUpY(int y) { return ClipRound(y * scaleY); } +int AwtWin32GraphicsDevice::ScaleUpAbsY(int y) +{ + LONG screen = pMonitorInfo->rcMonitor.top; + return screen + ClipRound((y - screen) * scaleY); +} + int AwtWin32GraphicsDevice::ScaleDownX(int x) { return ClipRound(x / scaleX); } +int AwtWin32GraphicsDevice::ScaleDownAbsX(int x) +{ + LONG screen = pMonitorInfo->rcMonitor.left; + return screen + ClipRound((x - screen) / scaleX); +} + int AwtWin32GraphicsDevice::ScaleDownY(int y) { return ClipRound(y / scaleY); } +int AwtWin32GraphicsDevice::ScaleDownAbsY(int y) +{ + LONG screen = pMonitorInfo->rcMonitor.top; + return screen + ClipRound((y - screen) / scaleY); +} + int AwtWin32GraphicsDevice::ClipRound(double value) { value -= 0.5; @@ -666,11 +691,13 @@ int AwtWin32GraphicsDevice::ClipRound(double value) void AwtWin32GraphicsDevice::InitDesktopScales() { - float dpiX = -1.0f; - float dpiY = -1.0f; - GetScreenDpi(GetMonitor(), &dpiX, &dpiY); - if (dpiX > 0 && dpiY > 0) { - SetScale(dpiX / 96, dpiY / 96); + if (!disableScaleAutoRefresh) { + float dpiX = -1.0f; + float dpiY = -1.0f; + GetScreenDpi(GetMonitor(), &dpiX, &dpiY); + if (dpiX > 0 && dpiY > 0) { + SetScale(dpiX / 96, dpiY / 96); + } } } @@ -694,6 +721,11 @@ void AwtWin32GraphicsDevice::DisableOffscreenAcceleration() // REMIND: noop for now } +void AwtWin32GraphicsDevice::DisableScaleAutoRefresh() +{ + disableScaleAutoRefresh = TRUE; +} + /** * Invalidates the GraphicsDevice object associated with this * device by disabling offscreen acceleration and calling @@ -754,6 +786,21 @@ void AwtWin32GraphicsDevice::ResetAllMonitorInfo() } } +/** + * This function updates the scale factor for all monitors on the system. + */ +void AwtWin32GraphicsDevice::ResetAllDesktopScales() +{ + if (!Devices::GetInstance()){ + return; + } + Devices::InstanceAccess devices; + int devicesNum = devices->GetNumDevices(); + for (int deviceIndex = 0; deviceIndex < devicesNum; deviceIndex++) { + devices->GetDevice(deviceIndex)->InitDesktopScales(); + } +} + void AwtWin32GraphicsDevice::DisableOffscreenAccelerationForDevice( HMONITOR hMonitor) { @@ -1393,6 +1440,7 @@ JNIEXPORT void JNICALL AwtWin32GraphicsDevice *device = devices->GetDevice(screen); if (device != NULL ) { + device->DisableScaleAutoRefresh(); device->SetScale(scaleX, scaleY); } } @@ -1441,4 +1489,3 @@ Java_sun_awt_Win32GraphicsDevice_initNativeScale device->InitDesktopScales(); } } - diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h index d5fc0d57150d6..f298aad68da8c 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2020, 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 @@ -65,15 +65,20 @@ class AwtWin32GraphicsDevice { int GetDeviceIndex() { return screen; } void Release(); void DisableOffscreenAcceleration(); + void DisableScaleAutoRefresh(); void Invalidate(JNIEnv *env); void InitDesktopScales(); void SetScale(float scaleX, float scaleY); float GetScaleX(); float GetScaleY(); int ScaleUpX(int x); + int ScaleUpAbsX(int x); int ScaleUpY(int y); + int ScaleUpAbsY(int x); int ScaleDownX(int x); + int ScaleDownAbsX(int x); int ScaleDownY(int y); + int ScaleDownAbsY(int y); static int DeviceIndexForWindow(HWND hWnd); static jobject GetColorModel(JNIEnv *env, jboolean dynamic, @@ -88,6 +93,7 @@ class AwtWin32GraphicsDevice { static HMONITOR GetMonitor(int deviceIndex); static LPMONITORINFO GetMonitorInfo(int deviceIndex); static void ResetAllMonitorInfo(); + static void ResetAllDesktopScales(); static BOOL IsPrimaryPalettized() { return primaryPalettized; } static int GetDefaultDeviceIndex() { return primaryIndex; } static void DisableOffscreenAccelerationForDevice(HMONITOR hMonitor); @@ -117,6 +123,7 @@ class AwtWin32GraphicsDevice { Devices *devicesArray; float scaleX; float scaleY; + BOOL disableScaleAutoRefresh; static HDC MakeDCFromMonitor(HMONITOR); static int ClipRound(double value); diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp index e73c2615a079e..dbca3d778c8b7 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp @@ -153,17 +153,6 @@ struct SetFullScreenExclusiveModeStateStruct { jboolean isFSEMState; }; -// struct for _WindowDPIChange() method -struct ScaleStruct { - jobject window; - jint prevScreen; - jfloat prevScaleX; - jfloat prevScaleY; - jint screen; - jfloat scaleX; - jfloat scaleY; -}; - struct OverrideHandle { jobject frame; HWND handle; @@ -179,10 +168,6 @@ jfieldID AwtWindow::autoRequestFocusID; jfieldID AwtWindow::securityWarningWidthID; jfieldID AwtWindow::securityWarningHeightID; -jfieldID AwtWindow::sysXID; -jfieldID AwtWindow::sysYID; -jfieldID AwtWindow::sysWID; -jfieldID AwtWindow::sysHID; jfieldID AwtWindow::windowTypeID; jmethodID AwtWindow::notifyWindowStateChangedMID; @@ -1128,20 +1113,19 @@ AwtWindow* AwtWindow::Create(jobject self, jobject parent) // specify WS_EX_TOOLWINDOW to remove parentless windows from taskbar exStyle |= WS_EX_TOOLWINDOW; } + jint x = env->GetIntField(target, AwtComponent::xID); + jint y = env->GetIntField(target, AwtComponent::yID); + jint width = env->GetIntField(target, AwtComponent::widthID); + jint height = env->GetIntField(target, AwtComponent::heightID); + window->CreateHWnd(env, L"", style, exStyle, - 0, 0, 0, 0, + x, y, width, height, (awtParent != NULL) ? awtParent->GetHWnd() : NULL, NULL, ::GetSysColor(COLOR_WINDOWTEXT), ::GetSysColor(COLOR_WINDOW), self); - - jint x = env->GetIntField(target, AwtComponent::xID); - jint y = env->GetIntField(target, AwtComponent::yID); - jint width = env->GetIntField(target, AwtComponent::widthID); - jint height = env->GetIntField(target, AwtComponent::heightID); - /* * Initialize icon as inherited from parent if it exists */ @@ -1151,13 +1135,7 @@ AwtWindow* AwtWindow::Create(jobject self, jobject parent) window->m_iconInherited = TRUE; } window->DoUpdateIcon(); - - - /* - * Reshape here instead of during create, so that a WM_NCCALCSIZE - * is sent. - */ - window->Reshape(x, y, width, height); + window->RecalcNonClient(); } } catch (...) { env->DeleteLocalRef(target); @@ -1215,6 +1193,48 @@ void AwtWindow::moveToDefaultLocation() { VERIFY(::SetWindowPos(GetHWnd(), NULL, defLoc.left, defLoc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER)); } +/** + * Override AwtComponent::Reshape() to handle absolute screen coordinates used + * by the top-level windows. + */ +void AwtWindow::Reshape(int x, int y, int w, int h) { + if (IsEmbeddedFrame()) { + // Not the "real" top level window + return AwtComponent::Reshape(x, y, w, h); + } + // Yes, use x,y in user's space to find the nearest monitor in device space. + POINT pt = {x + w / 2, y + h / 2}; + Devices::InstanceAccess devices; + HMONITOR monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(monitor); + AwtWin32GraphicsDevice *device = devices->GetDevice(screen); + // Try to set the correct size and jump to the correct location, even if it is + // on the different monitor. Note that for the "size" we use the current + // monitor, so the WM_DPICHANGED will adjust it for the "target" monitor. + int scaleUpAbsX = device == NULL ? x : device->ScaleUpAbsX(x); + int scaleUpAbsY = device == NULL ? y : device->ScaleUpAbsY(y); + ReshapeNoScale(scaleUpAbsX, scaleUpAbsY, ScaleUpX(w), ScaleUpY(h)); + // The window manager may tweak the size for different reasons, so try + // to make sure our window has the correct size in the user's space. + // NOOP if the size was changed already or changing is in progress. + RECT rc; + ::GetWindowRect(GetHWnd(), &rc); + ReshapeNoScale(rc.left, rc.top, ScaleUpX(w), ScaleUpY(h)); + // the window manager may ignore our "SetWindowPos" request, in this, + // case the WmMove/WmSize will not come and we need to manually resync + // the "java.awt.Window" locations, because "java.awt.Window" already + // uses location ignored by the window manager. + ::GetWindowRect(GetHWnd(), &rc); + if (x != ScaleDownAbsX(rc.left) || y != ScaleDownAbsY(rc.top)) { + WmMove(rc.left, rc.top); + } + int userW = ScaleDownX(rc.right - rc.left); + int userH = ScaleDownY(rc.bottom - rc.top); + if (w != userW || h != userH) { + WmSize(SIZENORMAL, rc.right - rc.left, rc.bottom - rc.top); + } +} + void AwtWindow::Show() { m_visible = true; @@ -1774,6 +1794,15 @@ MsgRouting AwtWindow::WmShowWindow(BOOL show, UINT status) return AwtCanvas::WmShowWindow(show, status); } +void AwtWindow::WmDPIChanged(const LPARAM &lParam) { + // need to update the scales now, otherwise the ReshapeNoScale() will + // calculate the bounds wrongly + AwtWin32GraphicsDevice::ResetAllDesktopScales(); + RECT *r = (RECT *) lParam; + ReshapeNoScale(r->left, r->top, r->right - r->left, r->bottom - r->top); + CheckIfOnNewScreen(true); +} + /* * Override AwtComponent's move handling to first update the * java AWT target's position fields directly, since Windows @@ -1789,30 +1818,21 @@ MsgRouting AwtWindow::WmMove(int x, int y) // NOTE: See also AwtWindow::Reshape return mrDoDefault; } - - if (m_screenNum == -1) { - // Set initial value - m_screenNum = GetScreenImOn(); - } - else { - CheckIfOnNewScreen(); - } + // Check for the new screen and update the java peer + CheckIfOnNewScreen(false); // postpone if different DPI /* Update the java AWT target component's fields directly */ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (env->EnsureLocalCapacity(1) < 0) { return mrConsume; } - jobject peer = GetPeer(env); - jobject target = env->GetObjectField(peer, AwtObject::targetID); + jobject target = GetTarget(env); RECT rect; ::GetWindowRect(GetHWnd(), &rect); - (env)->SetIntField(target, AwtComponent::xID, ScaleDownX(rect.left)); - (env)->SetIntField(target, AwtComponent::yID, ScaleDownY(rect.top)); - (env)->SetIntField(peer, AwtWindow::sysXID, ScaleDownX(rect.left)); - (env)->SetIntField(peer, AwtWindow::sysYID, ScaleDownY(rect.top)); + (env)->SetIntField(target, AwtComponent::xID, ScaleDownAbsX(rect.left)); + (env)->SetIntField(target, AwtComponent::yID, ScaleDownAbsY(rect.top)); SendComponentEvent(java_awt_event_ComponentEvent_COMPONENT_MOVED); env->DeleteLocalRef(target); @@ -1857,13 +1877,22 @@ MsgRouting AwtWindow::WmSizing() MsgRouting AwtWindow::WmEnterSizeMove() { m_winSizeMove = TRUE; + // Below is a workaround, see CheckWindowDPIChange + Devices::InstanceAccess devices; + AwtWin32GraphicsDevice* device = devices->GetDevice(m_screenNum); + if (device) { + prevScaleRec.screen = m_screenNum; + prevScaleRec.scaleX = device->GetScaleX(); + prevScaleRec.scaleY = device->GetScaleY(); + } + // Above is a workaround return mrDoDefault; } MsgRouting AwtWindow::WmExitSizeMove() { m_winSizeMove = FALSE; - CheckWindowDPIChange(); + CheckWindowDPIChange(); // workaround return mrDoDefault; } @@ -1880,6 +1909,8 @@ MsgRouting AwtWindow::WmSize(UINT type, int w, int h) UpdateSecurityWarningVisibility(); return mrDoDefault; } + // Check for the new screen and update the java peer + CheckIfOnNewScreen(false); // postpone if different DPI JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); if (env->EnsureLocalCapacity(1) < 0) @@ -1887,15 +1918,8 @@ MsgRouting AwtWindow::WmSize(UINT type, int w, int h) jobject target = GetTarget(env); // fix 4167248 : ensure the insets are up-to-date before using BOOL insetsChanged = UpdateInsets(NULL); - int newWidth = w + m_insets.left + m_insets.right; - int newHeight = h + m_insets.top + m_insets.bottom; - - (env)->SetIntField(target, AwtComponent::widthID, ScaleDownX(newWidth)); - (env)->SetIntField(target, AwtComponent::heightID, ScaleDownY(newHeight)); - - jobject peer = GetPeer(env); - (env)->SetIntField(peer, AwtWindow::sysWID, ScaleDownX(newWidth)); - (env)->SetIntField(peer, AwtWindow::sysHID, ScaleDownY(newHeight)); + (env)->SetIntField(target, AwtComponent::widthID, ScaleDownX(w)); + (env)->SetIntField(target, AwtComponent::heightID, ScaleDownY(h)); if (!AwtWindow::IsResizing()) { WindowResized(); @@ -1977,6 +2001,11 @@ LRESULT AwtWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) LRESULT retValue = 0L; switch(message) { + case WM_DPICHANGED: { + WmDPIChanged(lParam); + mr = mrConsume; + break; + } case WM_GETICON: mr = WmGetIcon(wParam, retValue); break; @@ -2120,14 +2149,28 @@ int AwtWindow::GetScreenImOn() { return scrnNum; } -/* Check to see if we've been moved onto another screen. +/* + * Check to see if we've been moved onto another screen. * If so, update internal data, surfaces, etc. */ - -void AwtWindow::CheckIfOnNewScreen() { +void AwtWindow::CheckIfOnNewScreen(BOOL force) { int curScrn = GetScreenImOn(); if (curScrn != m_screenNum) { // we've been moved + // if moved from one monitor to another with different DPI, we should + // update the m_screenNum only if the size was updated as well in the + // WM_DPICHANGED. + Devices::InstanceAccess devices; + AwtWin32GraphicsDevice* oldDevice = devices->GetDevice(m_screenNum); + AwtWin32GraphicsDevice* newDevice = devices->GetDevice(curScrn); + if (!force && m_winSizeMove && oldDevice && newDevice) { + if (oldDevice->GetScaleX() != newDevice->GetScaleX() + || oldDevice->GetScaleY() != newDevice->GetScaleY()) { + // scales are different, wait for WM_DPICHANGED + return; + } + } + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jclass peerCls = env->GetObjectClass(m_peerObject); @@ -2149,65 +2192,37 @@ void AwtWindow::CheckIfOnNewScreen() { } } +// The shared code is not ready to the top-level window which crosses a few +// monitors with different DPI. Popup windows will start to use wrong screen, +// will be placed in the wrong place and will use the wrong size, see 8249164 +// So we will "JUMP TO" the new screen. void AwtWindow::CheckWindowDPIChange() { - - if (prevScaleRec.screen != -1 ) { - float prevScaleX = prevScaleRec.scaleX; - float prevScaleY = prevScaleRec.scaleY; - - if (prevScaleX >= 1 && prevScaleY >= 1) { - Devices::InstanceAccess devices; - AwtWin32GraphicsDevice* device = devices->GetDevice(m_screenNum); - if (device) { - float scaleX = device->GetScaleX(); - float scaleY = device->GetScaleY(); - if (prevScaleX != scaleX || prevScaleY != scaleY) { - WindowDPIChange(prevScaleRec.screen, prevScaleX, prevScaleY, - m_screenNum, scaleX, scaleY); - } - } - } - prevScaleRec.screen = -1; - } -} - -void AwtWindow::WindowDPIChange(int prevScreen, - float prevScaleX, float prevScaleY, - int screen, float scaleX, - float scaleY) -{ - int x; - int y; - int w; - int h; - RECT rect; - - if (prevScaleX == scaleX && prevScaleY == scaleY) { - return; - } - - ::GetWindowRect(GetHWnd(), &rect); - x = rect.left; - y = rect.top; - w = (rect.right - rect.left) * scaleX / prevScaleX; - h = (rect.bottom - rect.top) * scaleY / prevScaleY; - - if (prevScreen != screen) { + if (prevScaleRec.screen != -1 && prevScaleRec.screen != m_screenNum) { Devices::InstanceAccess devices; - AwtWin32GraphicsDevice* device = devices->GetDevice(screen); + AwtWin32GraphicsDevice *device = devices->GetDevice(m_screenNum); if (device) { - RECT bounds; - if (MonitorBounds(device->GetMonitor(), &bounds)) { - x = x < bounds.left ? bounds.left : x; - y = y < bounds.top ? bounds.top : y; - - x = (x + w > bounds.right) ? bounds.right - w : x; - y = (y + h > bounds.bottom) ? bounds.bottom - h : y; + if (prevScaleRec.scaleX != device->GetScaleX() + || prevScaleRec.scaleY != device->GetScaleY()) { + RECT rect; + ::GetWindowRect(GetHWnd(), &rect); + int x = rect.left; + int y = rect.top; + int w = rect.right - rect.left; + int h = rect.bottom - rect.top; + RECT bounds; + if (MonitorBounds(device->GetMonitor(), &bounds)) { + x = x < bounds.left ? bounds.left : x; + y = y < bounds.top ? bounds.top : y; + x = (x + w > bounds.right) ? bounds.right - w : x; + y = (y + h > bounds.bottom) ? bounds.bottom - h : y; + } + ReshapeNoScale(x, y, w, h); } } + prevScaleRec.screen = -1; + prevScaleRec.scaleX = -1.0f; + prevScaleRec.scaleY = -1.0f; } - - ReshapeNoScale(x, y, w, h); } BOOL AwtWindow::IsFocusableWindow() { @@ -2582,15 +2597,11 @@ void AwtWindow::_ReshapeFrame(void *param) { env->SetIntField(target, AwtComponent::widthID, w = minWidth); - env->SetIntField(peer, AwtWindow::sysWID, - w); } if (h < minHeight) { env->SetIntField(target, AwtComponent::heightID, h = minHeight); - env->SetIntField(peer, AwtWindow::sysHID, - h); } } env->DeleteLocalRef(target); @@ -3257,39 +3268,6 @@ void AwtWindow::_GetNativeWindowSize(void* param) { env->DeleteGlobalRef(self); } -void AwtWindow::_WindowDPIChange(void* param) -{ - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - - ScaleStruct *ss = (ScaleStruct *)param; - jobject self = ss->window; - jint prevScreen = ss->prevScreen; - jfloat prevScaleX = ss->prevScaleX; - jfloat prevScaleY = ss->prevScaleY; - jint screen = ss->screen; - jfloat scaleX = ss->scaleX; - jfloat scaleY = ss->scaleY; - - PDATA pData; - JNI_CHECK_PEER_GOTO(self, ret); - AwtWindow *window = (AwtWindow *)pData; - - if (window->m_winSizeMove) { - if (window->prevScaleRec.screen == -1) { - window->prevScaleRec.screen = prevScreen; - window->prevScaleRec.scaleX = prevScaleX; - window->prevScaleRec.scaleY = prevScaleY; - } - } - else { - window->WindowDPIChange(prevScreen, prevScaleX, prevScaleY, - screen, scaleX, scaleY); - } - -ret: - env->DeleteGlobalRef(self); - delete ss; -} extern "C" int getSystemMetricValue(int msgType); extern "C" { @@ -3347,11 +3325,6 @@ Java_sun_awt_windows_WWindowPeer_initIDs(JNIEnv *env, jclass cls) { TRY; - CHECK_NULL(AwtWindow::sysXID = env->GetFieldID(cls, "sysX", "I")); - CHECK_NULL(AwtWindow::sysYID = env->GetFieldID(cls, "sysY", "I")); - CHECK_NULL(AwtWindow::sysWID = env->GetFieldID(cls, "sysW", "I")); - CHECK_NULL(AwtWindow::sysHID = env->GetFieldID(cls, "sysH", "I")); - AwtWindow::windowTypeID = env->GetFieldID(cls, "windowType", "Ljava/awt/Window$Type;"); @@ -3991,33 +3964,6 @@ Java_sun_awt_windows_WWindowPeer_repositionSecurityWarning(JNIEnv *env, CATCH_BAD_ALLOC; } -/* -* Class: sun_awt_windows_WWindowPeer -* Method: windowDPIChange -* Signature: (IFFIFF)V -*/ -JNIEXPORT void JNICALL -Java_sun_awt_windows_WWindowPeer_windowDPIChange(JNIEnv *env, jobject self, - jint prevScreen, jfloat prevScaleX, jfloat prevScaleY, - jint screen, jfloat scaleX, jfloat scaleY) -{ - TRY; - - ScaleStruct *ss = new ScaleStruct; - ss->window = env->NewGlobalRef(self); - ss->prevScreen = prevScreen; - ss->prevScaleX = prevScaleX; - ss->prevScaleY = prevScaleY; - ss->screen = screen; - ss->scaleX = scaleX; - ss->scaleY = scaleY; - - AwtToolkit::GetInstance().InvokeFunction(AwtWindow::_WindowDPIChange, ss); - // global refs and ss are deleted in _WindowDPIChange - - CATCH_BAD_ALLOC; -} - /* * Class: sun_awt_windows_WLightweightFramePeer * Method: overrideNativeHandle diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Window.h b/src/java.desktop/windows/native/libawt/windows/awt_Window.h index 38f012864dfa5..6e035cc8f38dc 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Window.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, 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 @@ -58,12 +58,6 @@ class AwtWindow : public AwtCanvas { static jfieldID securityWarningHeightID; /* sun.awt.windows.WWindowPeer field and method IDs */ - // The coordinates at the peer. - static jfieldID sysXID; - static jfieldID sysYID; - static jfieldID sysWID; - static jfieldID sysHID; - static jfieldID windowTypeID; static jmethodID notifyWindowStateChangedMID; @@ -129,6 +123,7 @@ class AwtWindow : public AwtCanvas { return FALSE; } + virtual void Reshape(int x, int y, int w, int h); virtual void Invalidate(RECT* r); virtual void Show(); virtual void SetResizable(BOOL isResizable); @@ -136,7 +131,7 @@ class AwtWindow : public AwtCanvas { virtual void RecalcNonClient(); virtual void RedrawNonClient(); virtual int GetScreenImOn(); - virtual void CheckIfOnNewScreen(); + virtual void CheckIfOnNewScreen(BOOL force); virtual void Grab(); virtual void Ungrab(); virtual void Ungrab(BOOL doPost); @@ -248,7 +243,6 @@ class AwtWindow : public AwtCanvas { static void _RepositionSecurityWarning(void* param); static void _SetFullScreenExclusiveModeState(void* param); static void _GetNativeWindowSize(void* param); - static void _WindowDPIChange(void* param); static void _OverrideHandle(void *param); inline static BOOL IsResizing() { @@ -409,8 +403,7 @@ class AwtWindow : public AwtCanvas { void InitOwner(AwtWindow *owner); void CheckWindowDPIChange(); - void WindowDPIChange(int prevScreen, float prevScaleX, float prevScaleY, - int newScreen, float scaleX, float scaleY); + void WmDPIChanged(const LPARAM &lParam); Type m_windowType; void InitType(JNIEnv *env, jobject peer); diff --git a/src/java.desktop/windows/native/libawt/windows/awtmsg.h b/src/java.desktop/windows/native/libawt/windows/awtmsg.h index ba8a44925919a..c4f85fad41c86 100644 --- a/src/java.desktop/windows/native/libawt/windows/awtmsg.h +++ b/src/java.desktop/windows/native/libawt/windows/awtmsg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, 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 @@ -41,6 +41,10 @@ extern const UINT SYSCOMMAND_IMM; * See winuser.h for details. */ +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif //WM_DPICHANGED + #ifndef WM_MOUSEWHEEL #define WM_MOUSEWHEEL 0x020A #endif //WM_MOUSEWHEEL diff --git a/test/jdk/java/awt/Component/SetComponentsBounds/SetComponentsBounds.java b/test/jdk/java/awt/Component/SetComponentsBounds/SetComponentsBounds.java new file mode 100644 index 0000000000000..2967bc17f27bf --- /dev/null +++ b/test/jdk/java/awt/Component/SetComponentsBounds/SetComponentsBounds.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2020, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Button; +import java.awt.Canvas; +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Component; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Label; +import java.awt.List; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.ScrollPane; +import java.awt.Scrollbar; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.Window; + +/** + * @test + * @key headful + * @bug 8211999 + * @run main/othervm SetComponentsBounds + * @run main/othervm -Dsun.java2d.uiScale=1 SetComponentsBounds + * @run main/othervm -Dsun.java2d.uiScale=2.25 SetComponentsBounds + */ +public final class SetComponentsBounds { + + private static final int X = 111; + private static final int Y = 222; + private static final int WIDTH = 321; + private static final int HEIGHT = 123; + + public static void main(String[] args) throws Exception { + var ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + for (GraphicsDevice gd : ge.getScreenDevices()) { + test(gd.getDefaultConfiguration(), true); + test(gd.getDefaultConfiguration(), false); + } + } + + private static void test(GraphicsConfiguration gc, boolean visible) throws Exception { + Rectangle screen = gc.getBounds(); + Window frame = new Frame(); + try { + frame.setLayout(null); // trigger use the minimum size of + // the peer + frame.setBounds(screen.x + 100, screen.y + 100, 500, 500); + frame.add(new Button()); + frame.add(new Canvas()); + frame.add(new Checkbox()); + frame.add(new Choice()); + frame.add(new Label()); + frame.add(new List()); + frame.add(new Scrollbar()); + frame.add(new ScrollPane()); + frame.add(new TextArea()); + frame.add(new TextField()); + for (Component comp : frame.getComponents()) { + comp.setBounds(X, Y, WIDTH, HEIGHT); + } + if (visible) { + frame.setVisible(true); + } else { + frame.pack(); + } + Robot robot = new Robot(); + robot.waitForIdle(); + checkGC(gc, frame); + for (Component comp : frame.getComponents()) { + Rectangle bounds = comp.getBounds(); + if (bounds.x != X || bounds.y != Y || bounds.width != WIDTH) { + System.err.println("Screen bounds:" + screen); + System.err.println("Component:" + comp); + throw new RuntimeException("Wrong bounds:" + bounds); + } + if (bounds.height > HEIGHT) { + // different check for HEIGHT, it depends on the font + throw new RuntimeException("Wrong height:" + bounds.height); + } + checkGC(gc, comp); + } + } finally { + frame.dispose(); + } + } + + private static void checkGC(GraphicsConfiguration gc, Component comp) { + GraphicsConfiguration compGC = comp.getGraphicsConfiguration(); + if (compGC != gc) { + System.err.println("Expected GC:" + gc); + System.err.println("Actual GC:" + compGC); + throw new RuntimeException(); + } + } +} diff --git a/test/jdk/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java b/test/jdk/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java index e7fb0b8c6a067..e186e7ac1320a 100644 --- a/test/jdk/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java +++ b/test/jdk/java/awt/EmbeddedFrame/EmbeddedFrameGrabTest/EmbeddedFrameGrabTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, 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 @@ -24,7 +24,7 @@ /** * @test * @key headful - * @bug 6345003 8171363 + * @bug 6345003 8171363 8211999 * @summary grab problems with EmbeddedFrame * @requires (os.family == "windows") * @modules java.desktop/java.awt.peer @@ -67,6 +67,7 @@ private void init() throws Exception { final Frame frame = new Frame("AWT Frame"); frame.pack(); frame.setSize(200, 200); + frame.setLocationRelativeTo(null); FramePeer frame_peer = AWTAccessor.getComponentAccessor() .getPeer(frame); Class comp_peer_class @@ -88,6 +89,7 @@ private void init() throws Exception { final Panel p = new Panel(); p.setLayout(new BorderLayout()); embedded_frame.add(p, BorderLayout.CENTER); + embedded_frame.setBounds(0, 0, 150, 150); embedded_frame.validate(); p.add(combo); p.validate(); diff --git a/test/jdk/java/awt/Frame/MaximizedToOppositeScreen/MaximizedToOppositeScreenSmall.java b/test/jdk/java/awt/Frame/MaximizedToOppositeScreen/MaximizedToOppositeScreenSmall.java index eac72fd0fbbaa..bd749cc94a99a 100644 --- a/test/jdk/java/awt/Frame/MaximizedToOppositeScreen/MaximizedToOppositeScreenSmall.java +++ b/test/jdk/java/awt/Frame/MaximizedToOppositeScreen/MaximizedToOppositeScreenSmall.java @@ -21,6 +21,7 @@ * questions. */ +import java.awt.Dimension; import java.awt.Frame; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; @@ -30,7 +31,7 @@ /** * @test - * @bug 8176359 8231564 + * @bug 8176359 8231564 8211999 * @key headful * @requires (os.family == "windows" | os.family == "mac") * @summary setMaximizedBounds() should work if set to the screen other than @@ -58,15 +59,23 @@ public static void main(String[] args) throws Exception { Rectangle framAt = gd1.getDefaultConfiguration().getBounds(); framAt.grow(-framAt.width / 2 + 100, -framAt.height / 2 + 100); for (GraphicsDevice gd2 : gds) { - Rectangle maxTo = gd2.getDefaultConfiguration().getBounds(); - maxTo.grow(-maxTo.width / 2 + 120, -maxTo.height / 2 + 120); Frame frame = new Frame(gd1.getDefaultConfiguration()); try { + frame.setLayout(null); // trigger use the minimum size of + // the peer frame.setBounds(framAt); + frame.setVisible(true); robot.waitForIdle(); robot.delay(1000); + Dimension minimumSize = frame.getMinimumSize(); + minimumSize.width = Math.max(minimumSize.width, 120); + minimumSize.height = Math.max(minimumSize.height, 120); + Rectangle maxTo = gd2.getDefaultConfiguration().getBounds(); + maxTo.grow(-maxTo.width / 2 + minimumSize.width, + -maxTo.height / 2 + minimumSize.height); + frame.setMaximizedBounds(maxTo); frame.setExtendedState(Frame.MAXIMIZED_BOTH); robot.waitForIdle(); diff --git a/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java b/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java new file mode 100644 index 0000000000000..d444ee5f0f1be --- /dev/null +++ b/test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2020, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.DisplayMode; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Rectangle; + +/** + * @test + * @bug 8211999 + * @key headful + * @summary verifies the full-screen window bounds and graphics configuration + */ +public final class FullscreenWindowProps { + + public static void main(String[] args) throws Exception { + var ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice gd = ge.getDefaultScreenDevice(); + + if (!gd.isFullScreenSupported()) { + return; + } + + Frame frame = new Frame() { + @Override + public void paint(Graphics g) { + super.paint(g); + g.setColor(Color.GREEN); + g.fillRect(0, 0, getWidth(), getHeight()); + } + }; + try { + frame.setBackground(Color.MAGENTA); + frame.setVisible(true); + gd.setFullScreenWindow(frame); + Thread.sleep(4000); + + for (DisplayMode dm : gd.getDisplayModes()) { + if (dm.getWidth() == 1024 && dm.getHeight() == 768) { + gd.setDisplayMode(dm); + Thread.sleep(4000); + break; + } + } + + GraphicsConfiguration frameGC = frame.getGraphicsConfiguration(); + Rectangle frameBounds = frame.getBounds(); + + GraphicsConfiguration screenGC = gd.getDefaultConfiguration(); + Rectangle screenBounds = screenGC.getBounds(); + + if (frameGC != screenGC) { + System.err.println("Expected: " + screenGC); + System.err.println("Actual: " + frameGC); + throw new RuntimeException(); + } + + checkSize(frameBounds.x, screenBounds.x, "x"); + checkSize(frameBounds.y, screenBounds.y, "Y"); + checkSize(frameBounds.width, screenBounds.width, "width"); + checkSize(frameBounds.height, screenBounds.height, "height"); + } finally { + gd.setFullScreenWindow(null); + frame.dispose(); + Thread.sleep(10000); + } + } + + private static void checkSize(int actual, int expected, String prop) { + if (Math.abs(actual - expected) > 30) { // let's allow size variation, + // the bug is reproduced anyway + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + throw new RuntimeException(prop + " is wrong"); + } + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/List/ListMultipleSelectTest/ListMultipleSelectTest.java b/test/jdk/java/awt/List/ListMultipleSelectTest/ListMultipleSelectTest.java new file mode 100644 index 0000000000000..ef8ee7def0d1d --- /dev/null +++ b/test/jdk/java/awt/List/ListMultipleSelectTest/ListMultipleSelectTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1996, 2020, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; + +/** + * @test + * @bug 4909485 8211999 + * @key headful + */ +public final class ListMultipleSelectTest { + + private static List aList; + private static Panel panel; + private static Point p; + private static Robot robot; + private static int[] selected; + + public static void main(String[] args) throws Exception { + Frame frame = new Frame(); + try { + panel = new Panel(); + aList = new List(); + aList.add("Test item1"); + aList.add("Test item2"); + aList.add("Test item3"); + aList.add("Test item4"); + + frame.setLayout(new FlowLayout()); //list should fill whole frame's space + panel.add(aList); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + panel.setVisible(true); + frame.add(panel); + frame.setVisible(true); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(" InterruptedException. Test failed. "); + } + + Dimension listSize = aList.getSize(); + p = aList.getLocationOnScreen(); + int stepY = listSize.height / aList.getItemCount(); + +// System.out.println("itemCount = "+aList.getItemCount()); +// System.out.println("Size Of aList="+ listSize); +// System.out.println("stepY = "+stepY); +// System.out.println("Point:" +p); + System.out.println("Multiple mode is ON"); + aList.setMultipleMode(true); +//================================================= + robot = new Robot(); + robot.setAutoDelay(0); + robot.setAutoWaitForIdle(false); + robot.delay(10); + robot.waitForIdle(); + +//================================================= + + for (int i = 0; i < aList.getItemCount(); i++) { + //select all items in the List + mousePress(p.x + listSize.width / 2, p.y + stepY / 2 + stepY * i); + } + + selected = aList.getSelectedIndexes(); + System.out.println("Multiple mode is ON"); + aList.setMultipleMode(true); + int[] newSelected = aList.getSelectedIndexes(); + if (!java.util.Arrays.equals(newSelected, selected)) { + throw new RuntimeException(" Incorrect item remains selected " + + "after setMultipleMode(true). "); + } + + aList.setMultipleMode(false); + System.out.println("Multiple mode is OFF"); + selected = aList.getSelectedIndexes(); + if (selected[0] != 3 || selected.length != 1) { + throw new RuntimeException(" Incorrect item remains selected " + + "after setMultipleMode(false) or it is more then one " + + "item remaining.Forward. "); + } + + System.out.println("Multiple mode is ON"); + aList.setMultipleMode(true); + + if (selected[0] != 3 || selected.length != 1) { + throw new RuntimeException(" Incorrect item remains selected " + + "after setMultipleMode(true) or it is more then one " + + "item remaining. "); + } + + deselectAll(); + for (int i = aList.getItemCount() - 1; i >= 0; i--) { + mousePress(p.x + listSize.width / 2, p.y + stepY / 2 + stepY * i); + } + + System.out.println("Multiple mode is OFF"); + aList.setMultipleMode(false); + + selected = aList.getSelectedIndexes(); + if (selected[0] != 0 || selected.length != 1) { + throw new RuntimeException(" Incorrect item remains selected " + + "after setMultipleMode(false) or it is more then one " + + "item remaining.Backward. "); + } + System.out.println("Test succeeded."); + } finally { + frame.dispose(); + } + } + + private static void mousePress(int x, int y) { + robot.mouseMove(x, y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.delay(1000); + } + + private static void deselectAll() { + for (int i = 0; i < selected.length; i++) { + aList.deselect(selected[i]); + } + } +} diff --git a/test/jdk/java/awt/Multiscreen/MouseEventTest/MouseEventTest.java b/test/jdk/java/awt/Multiscreen/MouseEventTest/MouseEventTest.java index 45d9aa5c80b61..c6494dc314ba5 100644 --- a/test/jdk/java/awt/Multiscreen/MouseEventTest/MouseEventTest.java +++ b/test/jdk/java/awt/Multiscreen/MouseEventTest/MouseEventTest.java @@ -24,7 +24,7 @@ /* @test @key headful - @bug 8017472 + @bug 8017472 8211999 @summary MouseEvent has wrong coordinates when using multiple monitors @run main MouseEventTest */ diff --git a/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java index 061b8953200df..57419b0ac5aa9 100644 --- a/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java +++ b/test/jdk/java/awt/Robot/CheckCommonColors/CheckCommonColors.java @@ -24,6 +24,8 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; @@ -38,7 +40,7 @@ /** * @test * @key headful - * @bug 8215105 + * @bug 8215105 8211999 * @summary tests that Robot can capture the common colors without artifacts */ public final class CheckCommonColors { @@ -48,16 +50,20 @@ public final class CheckCommonColors { public static void main(final String[] args) throws Exception { robot = new Robot(); - try { - test(); - } finally { - frame.dispose(); + var ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + for (GraphicsDevice gd : ge.getScreenDevices()) { + try { + test(gd.getDefaultConfiguration().getBounds()); + } finally { + frame.dispose(); + } } } - private static void test() { + private static void test(Rectangle screen) { frame.setSize(400, 400); - frame.setLocationRelativeTo(null); + frame.setLocation((int)screen.getCenterX() - 200, + (int)screen.getCenterY() - 200); frame.setUndecorated(true); for (final Color color : List.of(Color.WHITE, Color.LIGHT_GRAY, Color.GRAY, Color.DARK_GRAY, @@ -69,16 +75,25 @@ private static void test() { robot.waitForIdle(); frame.setBackground(color); frame.setVisible(true); - checkPixels(color); + checkPixels(color, true); + checkPixels(color, false); } } - private static void checkPixels(final Color color) { + private static void checkPixels(final Color color, boolean useRect) { + System.out.println("color = " + color + ", useRect = " + useRect); int attempt = 0; while (true) { Point p = frame.getLocationOnScreen(); p.translate(frame.getWidth() / 2, frame.getHeight() / 2); - Color pixel = robot.getPixelColor(p.x, p.y); + Color pixel; + Rectangle rect = new Rectangle(p.x, p.y, 1, 1); + if (useRect) { + BufferedImage bi = robot.createScreenCapture(rect); + pixel = new Color(bi.getRGB(0, 0)); + } else { + pixel = robot.getPixelColor(rect.x, rect.y); + } if (color.equals(pixel)) { return; } diff --git a/test/jdk/java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java b/test/jdk/java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java index 5fe2f9b2e5c4e..b6a186290225a 100644 --- a/test/jdk/java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java +++ b/test/jdk/java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, 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 @@ -32,7 +32,7 @@ /** * @test * @key headful - * @bug 8201364 8232433 + * @bug 8201364 8232433 8211999 * @summary Component.getLocation() should returns correct location if * Component.setBounds() was ignored by the OS */ @@ -64,8 +64,11 @@ private static void test(final boolean undecorated) throws AWTException { Rectangle bounds = device.getDefaultConfiguration().getBounds(); test(robot, frame, bounds.x, bounds.y); test(robot, frame, bounds.width, bounds.y); + test(robot, frame, bounds.x + bounds.width, bounds.y); test(robot, frame, bounds.x, bounds.height); + test(robot, frame, bounds.x, bounds.y + bounds.height); test(robot, frame, bounds.width, bounds.height); + test(robot, frame, bounds.x + bounds.width, bounds.y + bounds.height); } frame.dispose(); } diff --git a/test/jdk/java/awt/Window/SlowMotion/SlowMotion.java b/test/jdk/java/awt/Window/SlowMotion/SlowMotion.java new file mode 100644 index 0000000000000..ac6c51ad62152 --- /dev/null +++ b/test/jdk/java/awt/Window/SlowMotion/SlowMotion.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.Window; + +/** + * @test + * @key headful + * @bug 8211999 + * @run main/timeout=300 SlowMotion + * @summary places the window on the screen outside of any insets, and waits to + * catch any strange window moving + */ +public final class SlowMotion { + + // some additional space, if getScreenInsets() does not work, say on Linux + private static final int SAFE = 100; + private static final int HEIGHT = 350; + private static final int WIDTH = 279; + private static Robot robot; + + public static void main(final String[] args) throws Exception { + robot = new Robot(); + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] sds = ge.getScreenDevices(); + + for (GraphicsDevice sd : sds) { + GraphicsConfiguration gc = sd.getDefaultConfiguration(); + Rectangle bounds = gc.getBounds(); + bounds.translate(SAFE, SAFE); + Point point = new Point(bounds.x, bounds.y); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + while (point.y < bounds.y + bounds.height - insets.bottom - HEIGHT - SAFE * 2) { + while (point.x < bounds.x + bounds.width - insets.right - WIDTH - SAFE * 2) { + test(point, new Frame()); + test(point, new Window(null)); + test(point, new Dialog((Dialog) null)); + point.translate(bounds.width / 6, 0); + } + point.setLocation(bounds.x, point.y + bounds.height / 5); + } + } + } + + private static void test(final Point loc, Window window) { + try { + window.setBounds(loc.x, loc.y, WIDTH, HEIGHT); + window.setVisible(true); + robot.delay(1000); // intentionally very slow, we try to catch + // very very last suspicion event + Rectangle bounds = window.getBounds(); + if (loc.x != bounds.x || loc.y != bounds.y + || bounds.width != WIDTH || bounds.height != HEIGHT) { + System.err.println("Component = " + window); + System.err.println("Actual bounds = " + bounds); + System.err.println("Expected location = " + loc); + System.err.println("Expected width = " + WIDTH); + System.err.println("Expected height = " + HEIGHT); + throw new RuntimeException(); + } + } finally { + window.dispose(); + } + } +} diff --git a/test/jdk/java/awt/Window/WindowSizeDifferentScreens/WindowSizeDifferentScreens.java b/test/jdk/java/awt/Window/WindowSizeDifferentScreens/WindowSizeDifferentScreens.java new file mode 100644 index 0000000000000..4ac5aeeac1a70 --- /dev/null +++ b/test/jdk/java/awt/Window/WindowSizeDifferentScreens/WindowSizeDifferentScreens.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2020, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Window; + +/** + * @test + * @key headful + * @bug 8211999 + * @summary The test creates the packed/unpacked top level components on the + * different screens and compares their bounds + * @run main/othervm WindowSizeDifferentScreens + * @run main/othervm -Dsun.java2d.uiScale=1 WindowSizeDifferentScreens + * @run main/othervm -Dsun.java2d.uiScale=1.25 WindowSizeDifferentScreens + */ +public final class WindowSizeDifferentScreens { + + public static void main(String[] args) throws Exception { + test("window"); + test("dialog"); + test("frame"); + } + + private static void test(String top) throws Exception { + var ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + Robot robot = new Robot(); + Window main = getTopLevel(top); + try { + main.setVisible(true); + robot.waitForIdle(); + main.setSize(500, 500); + robot.waitForIdle(); + for (GraphicsDevice gd : ge.getScreenDevices()) { + Rectangle bounds = gd.getDefaultConfiguration().getBounds(); + Point point = bounds.getLocation(); + point.translate(100, 100); + main.setLocation(point); + main.setBackground(Color.RED); + robot.waitForIdle(); + + Window packed = getTopLevel(top); + Window unpacked = getTopLevel(top); + try { + packed.pack(); + robot.waitForIdle(); + packed.setBackground(Color.GREEN); + unpacked.setBackground(Color.BLUE); + packed.setSize(500, 500); + unpacked.setSize(500, 500); + packed.setLocation(point); + unpacked.setLocation(point); + robot.waitForIdle(); + packed.setVisible(true); + unpacked.setVisible(true); + robot.waitForIdle(); + Rectangle mBounds = main.getBounds(); + Rectangle pBounds = packed.getBounds(); + Rectangle uBounds = unpacked.getBounds(); + + if (!mBounds.equals(uBounds) || + !mBounds.equals(pBounds)) { + System.err.println("Expected bounds: " + mBounds); + System.err.println("Actual unpacked: " + uBounds); + System.err.println("Actual packed: " + pBounds); + throw new RuntimeException(); + } + } finally { + packed.dispose(); + unpacked.dispose(); + } + } + } finally { + main.dispose(); + } + } + + private static Window getTopLevel(String top) { + return switch (top) { + case "window" -> new Window(null); + case "dialog" -> new Dialog((Dialog) null); + case "frame" -> new Frame(); + default -> throw new IllegalArgumentException("Unexpected: " + top); + }; + } +} diff --git a/test/jdk/java/awt/dnd/Button2DragTest/Button2DragTest.java b/test/jdk/java/awt/dnd/Button2DragTest/Button2DragTest.java index 9400f854da124..75e32db4ed96e 100644 --- a/test/jdk/java/awt/dnd/Button2DragTest/Button2DragTest.java +++ b/test/jdk/java/awt/dnd/Button2DragTest/Button2DragTest.java @@ -23,10 +23,10 @@ import java.awt.Color; import java.awt.Frame; -import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Point; +import java.awt.Rectangle; import java.awt.Robot; import java.awt.datatransfer.StringSelection; import java.awt.dnd.DnDConstants; @@ -47,7 +47,7 @@ /** * @test * @key headful - * @bug 4955110 8238575 + * @bug 4955110 8238575 8211999 * @summary tests that DragSourceDragEvent.getDropAction() accords to its new * spec (does not depend on the user drop action) * @library ../../regtesthelpers @@ -57,6 +57,7 @@ */ public final class Button2DragTest { + private static final int SIZE = 200; private volatile boolean dropSuccess; private volatile boolean locationValid = true; @@ -79,8 +80,8 @@ public void run() { final DragSourceListener dragSourceListener = new DragSourceListener() { private void checkLocation(DragSourceEvent dsde) { if (!frame.getBounds().contains(dsde.getLocation())) { - System.err.println("Expected in" + frame.getBounds()); - System.err.println("Actual" + dsde.getLocation()); + System.err.println("Expected in: " + frame.getBounds()); + System.err.println("Actual: " + dsde.getLocation()); locationValid = false; } } @@ -130,8 +131,10 @@ public void drop(DropTargetDropEvent dtde) { frame.setBackground(Color.GREEN); frame.setUndecorated(true); - frame.setSize(200, 200); - frame.setLocationRelativeTo(null); + Rectangle screen = frame.getGraphicsConfiguration().getBounds(); + int x = (int) (screen.getCenterX() - SIZE / 2); + int y = (int) (screen.getCenterY() - SIZE / 2); + frame.setBounds(x, y, SIZE, SIZE); frame.setVisible(true); Robot robot = Util.createRobot(); diff --git a/test/jdk/javax/swing/JTextArea/8149849/DNDTextToScaledArea.java b/test/jdk/javax/swing/JTextArea/8149849/DNDTextToScaledArea.java index a68a11c5303e5..f0c4234b10e32 100644 --- a/test/jdk/javax/swing/JTextArea/8149849/DNDTextToScaledArea.java +++ b/test/jdk/javax/swing/JTextArea/8149849/DNDTextToScaledArea.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, 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 @@ -24,7 +24,10 @@ import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; import java.awt.Point; +import java.awt.Rectangle; import java.awt.Robot; import java.awt.event.InputEvent; import javax.swing.JFrame; @@ -35,13 +38,15 @@ /** * @test * @key headful - * @bug 8149849 + * @bug 8149849 8211999 * @summary [hidpi] DnD issues (cannot DnD from JFileChooser to JEditorPane or * other text component) when scale > 1 + * @run main/othervm DNDTextToScaledArea * @run main/othervm -Dsun.java2d.uiScale=2 DNDTextToScaledArea */ public class DNDTextToScaledArea { + private static final int SIZE = 300; private static final String TEXT = "ABCDEFGH"; private static JFrame frame; private static JTextArea srcTextArea; @@ -51,10 +56,17 @@ public class DNDTextToScaledArea { private static volatile boolean passed = false; public static void main(String[] args) throws Exception { + var lge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + for (GraphicsDevice device : lge.getScreenDevices()) { + test(device); + } + } + + private static void test(GraphicsDevice device) throws Exception { Robot robot = new Robot(); - robot.setAutoDelay(50); + robot.setAutoDelay(150); - SwingUtilities.invokeAndWait(DNDTextToScaledArea::createAndShowGUI); + SwingUtilities.invokeAndWait(() -> createAndShowGUI(device)); robot.waitForIdle(); SwingUtilities.invokeAndWait(() -> { @@ -62,6 +74,11 @@ public static void main(String[] args) throws Exception { dstPoint = getPoint(dstTextArea, 0.75); }); robot.waitForIdle(); + // check the destination + robot.mouseMove(dstPoint.x, dstPoint.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.waitForIdle(); dragAndDrop(robot, srcPoint, dstPoint); robot.waitForIdle(); @@ -77,11 +94,12 @@ public static void main(String[] args) throws Exception { } } - private static void createAndShowGUI() { - - frame = new JFrame(); - frame.setSize(300, 300); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + private static void createAndShowGUI(GraphicsDevice device) { + frame = new JFrame(device.getDefaultConfiguration()); + Rectangle screen = device.getDefaultConfiguration().getBounds(); + int x = (int) (screen.getCenterX() - SIZE / 2); + int y = (int) (screen.getCenterY() - SIZE / 2); + frame.setBounds(x, y, SIZE, SIZE); JPanel panel = new JPanel(new BorderLayout());