--- old/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java 2015-05-12 15:40:42.000000000 +0400 +++ new/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java 2015-05-12 15:40:42.000000000 +0400 @@ -543,9 +543,38 @@ return windowState; } + public Rectangle getMaximizedBounds() { + Object target = getTarget(); + return (target instanceof Frame) + ? ((Frame) target).getMaximizedBounds() : null; + } + + public Rectangle getDefaultMaximizedBounds() { + GraphicsConfiguration config = getGraphicsConfiguration(); + Insets insets = ((CGraphicsDevice) config.getDevice()).getScreenInsets(); + Rectangle toBounds = config.getBounds(); + return new Rectangle( + toBounds.x + insets.left, + toBounds.y + insets.top, + toBounds.width - insets.left - insets.right, + toBounds.height - insets.top - insets.bottom); + } + @Override public void setMaximizedBounds(Rectangle bounds) { - // TODO: not implemented + + bounds = (bounds == null) + ? getDefaultMaximizedBounds() + : constrainBounds(bounds); + platformWindow.setMaximizedBounds( + bounds.x, bounds.y, bounds.width, bounds.height); + } + + private void updateMaximizedBounds() { + Rectangle maximizedBounds = getMaximizedBounds(); + if (maximizedBounds == null) { + setMaximizedBounds(getDefaultMaximizedBounds()); + } } @Override @@ -635,6 +664,10 @@ // Second, update the graphics config and surface data final boolean isNewDevice = updateGraphicsDevice(); + if (isNewDevice) { + updateMaximizedBounds(); + } + if (resized || isNewDevice) { replaceSurfaceData(); updateMinimumSize(); @@ -1058,6 +1091,9 @@ if (updateGraphicsDevice()) { updateMinimumSize(); } + + updateMaximizedBounds(); + // Replace surface unconditionally, because internal state of the // GraphicsDevice could be changed. replaceSurfaceData(); --- old/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java 2015-05-12 15:40:42.000000000 +0400 +++ new/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java 2015-05-12 15:40:42.000000000 +0400 @@ -67,6 +67,11 @@ public void setBounds(int x, int y, int w, int h); /* + * Sets the maximized bounds. + */ + public default void setMaximizedBounds(int x, int y, int w, int h){} + + /* * Returns the graphics device where the window is. */ public GraphicsDevice getGraphicsDevice(); --- old/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2015-05-12 15:40:43.000000000 +0400 +++ new/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2015-05-12 15:40:43.000000000 +0400 @@ -51,6 +51,8 @@ private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr); private static native Insets nativeGetNSWindowInsets(long nsWindowPtr); private static native void nativeSetNSWindowBounds(long nsWindowPtr, double x, double y, double w, double h); + private static native void nativeSetNSWindowStandardFrame(long nsWindowPtr, + double x, double y, double w, double h); private static native void nativeSetNSWindowMinMax(long nsWindowPtr, double minW, double minH, double maxW, double maxH); private static native void nativePushNSWindowToBack(long nsWindowPtr); private static native void nativePushNSWindowToFront(long nsWindowPtr); @@ -246,6 +248,14 @@ ownerPtr, styleBits, bounds.x, bounds.y, bounds.width, bounds.height); setPtr(nativeWindowPtr); + _peer.setMaximizedBounds(_peer.getMaximizedBounds()); + if (_target instanceof Frame) { + Frame frame = (Frame) _target; + if (frame.getExtendedState() == Frame.MAXIMIZED_BOTH) { + maximize(); + } + } + if (target instanceof javax.swing.RootPaneContainer) { final javax.swing.JRootPane rootpane = ((javax.swing.RootPaneContainer)target).getRootPane(); if (rootpane != null) rootpane.addPropertyChangeListener("ancestor", new PropertyChangeListener() { @@ -474,6 +484,10 @@ nativeSetNSWindowBounds(getNSWindowPtr(), x, y, w, h); } + public void setMaximizedBounds(int x, int y, int w, int h) { + nativeSetNSWindowStandardFrame(getNSWindowPtr(), x, y, w, h); + } + private boolean isMaximized() { return undecorated ? this.normalBounds != null : CWrapper.NSWindow.isZoomed(getNSWindowPtr()); @@ -983,13 +997,11 @@ } private void checkZoom() { - if (target instanceof Frame && isVisible()) { - Frame targetFrame = (Frame)target; - if (targetFrame.getExtendedState() != Frame.MAXIMIZED_BOTH && isMaximized()) { - deliverZoom(true); - } else if (targetFrame.getExtendedState() == Frame.MAXIMIZED_BOTH && !isMaximized()) { - deliverZoom(false); - } + int state = peer.getState(); + if (state != Frame.MAXIMIZED_BOTH && isMaximized()) { + deliverZoom(true); + } else if (state == Frame.MAXIMIZED_BOTH && !isMaximized()) { + deliverZoom(false); } } --- old/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h 2015-05-12 15:40:44.000000000 +0400 +++ new/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h 2015-05-12 15:40:44.000000000 +0400 @@ -46,6 +46,7 @@ NSWindow *nsWindow; AWTWindow *ownerWindow; jint preFullScreenLevel; + NSRect standardFrame; } // An instance of either AWTWindow_Normal or AWTWindow_Panel @@ -59,7 +60,7 @@ @property (nonatomic) jint styleBits; @property (nonatomic) BOOL isEnabled; @property (nonatomic) jint preFullScreenLevel; - +@property (nonatomic) NSRect standardFrame; - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)javaPlatformWindow ownerWindow:owner --- old/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m 2015-05-12 15:40:44.000000000 +0400 +++ new/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m 2015-05-12 15:40:44.000000000 +0400 @@ -184,6 +184,7 @@ @synthesize isEnabled; @synthesize ownerWindow; @synthesize preFullScreenLevel; +@synthesize standardFrame; - (void) updateMinMaxSize:(BOOL)resizable { if (resizable) { @@ -509,6 +510,12 @@ // window exposing in _setVisible:(BOOL) } +- (NSRect)windowWillUseStandardFrame:(NSWindow *)window + defaultFrame:(NSRect)newFrame { + + return [self standardFrame]; +} + - (void) _deliverIconify:(BOOL)iconify { AWT_ASSERT_APPKIT_THREAD; @@ -953,6 +960,30 @@ /* * Class: sun_lwawt_macosx_CPlatformWindow + * Method: nativeSetNSWindowStandardFrame + * Signature: (JDDDD)V + */ +JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetNSWindowStandardFrame +(JNIEnv *env, jclass clazz, jlong windowPtr, jdouble originX, jdouble originY, + jdouble width, jdouble height) +{ + JNF_COCOA_ENTER(env); + + NSRect jrect = NSMakeRect(originX, originY, width, height); + + NSWindow *nsWindow = OBJC(windowPtr); + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ + + NSRect rect = ConvertNSScreenRect(NULL, jrect); + AWTWindow *window = (AWTWindow*)[nsWindow delegate]; + window.standardFrame = rect; + }]; + + JNF_COCOA_EXIT(env); +} + +/* + * Class: sun_lwawt_macosx_CPlatformWindow * Method: nativeSetNSWindowMinMax * Signature: (JDDDD)V */ --- old/test/java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java 2015-05-12 15:40:45.000000000 +0400 +++ new/test/java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java 2015-05-12 15:40:45.000000000 +0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2015, 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 @@ -22,67 +22,108 @@ */ import java.awt.*; - /* * @test * @summary When Frame.setExtendedState(Frame.MAXIMIZED_BOTH) * is called for a Frame after been called setMaximizedBounds() with * certain value, Frame bounds must equal to this value. * - * @library ../../../../lib/testlibrary - * @build ExtendedRobot * @run main SetMaximizedBounds */ public class SetMaximizedBounds { - Frame frame; - Rectangle bound; - boolean supported; - ExtendedRobot robot; - static Rectangle max = new Rectangle(100,100,400,400); - - public void doTest() throws Exception { - robot = new ExtendedRobot(); - - EventQueue.invokeAndWait( () -> { - frame = new Frame( "TestFrame "); - frame.setLayout(new FlowLayout()); - - if (Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { - supported = true; - frame.setMaximizedBounds(max); - } else { - supported = false; + public static void main(String[] args) throws Exception { + + //Supported platforms are Windows and OS X. + String os = System.getProperty("os.name").toLowerCase(); + if (!os.contains("windows") && !os.contains("os x")) { + return; + } + + if (!Toolkit.getDefaultToolkit(). + isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { + return; + } + + GraphicsEnvironment ge = GraphicsEnvironment. + getLocalGraphicsEnvironment(); + + if (ge.isHeadlessInstance()) { + return; + } + + for (GraphicsDevice gd : ge.getScreenDevices()) { + for (GraphicsConfiguration gc : gd.getConfigurations()) { + testMaximizedBounds(gc); } + } + } - frame.setSize(200, 200); + static void testMaximizedBounds(GraphicsConfiguration gc) throws Exception { + + Frame frame = null; + try { + + Rectangle maxArea = getMaximizedScreenArea(gc); + + Robot robot = new Robot(); + robot.setAutoDelay(50); + + frame = new Frame(); + Rectangle maximizedBounds = new Rectangle( + maxArea.x + maxArea.width / 6, + maxArea.y + maxArea.height / 6, + maxArea.width / 3, + maxArea.height / 3); + frame.setMaximizedBounds(maximizedBounds); + frame.setSize(maxArea.width / 8, maxArea.height / 8); frame.setVisible(true); - }); + robot.waitForIdle(); + + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + robot.waitForIdle(); + robot.delay(1000); - robot.waitForIdle(2000); - if (supported) { - EventQueue.invokeAndWait( () -> { - frame.setExtendedState(Frame.MAXIMIZED_BOTH); - }); - robot.waitForIdle(2000); - bound = frame.getBounds(); - if(!bound.equals(max)) + Rectangle bounds = frame.getBounds(); + if (!bounds.equals(maximizedBounds)) { throw new RuntimeException("The bounds of the Frame do not equal to what" - + " is specified when the frame is in Frame.MAXIMIZED_BOTH state"); - } else { - System.out.println("Frame.MAXIMIZED_BOTH not supported"); - } + + " is specified when the frame is in Frame.MAXIMIZED_BOTH state"); + } + + frame.setExtendedState(Frame.NORMAL); + robot.waitForIdle(); + robot.delay(1000); + + maximizedBounds = new Rectangle( + maxArea.x + maxArea.width / 10, + maxArea.y + maxArea.height / 10, + maxArea.width / 5, + maxArea.height / 5); + frame.setMaximizedBounds(maximizedBounds); + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + robot.waitForIdle(); + robot.delay(1000); - frame.dispose(); + bounds = frame.getBounds(); + if (!bounds.equals(maximizedBounds)) { + throw new RuntimeException("The bounds of the Frame do not equal to what" + + " is specified when the frame is in Frame.MAXIMIZED_BOTH state"); + } + } finally { + if (frame != null) { + frame.dispose(); + } + } } - public static void main(String[] args) throws Exception { - String os = System.getProperty("os.name").toLowerCase(); - System.out.println(os); - if (os.contains("windows") || os.contains("os x")) - new SetMaximizedBounds().doTest(); - else - System.out.println("Platform "+os+" is not supported. Supported platforms are Windows and OS X."); + static Rectangle getMaximizedScreenArea(GraphicsConfiguration gc) { + Rectangle bounds = gc.getBounds(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + return new Rectangle( + bounds.x + insets.left, + bounds.y + insets.top, + bounds.width - insets.left - insets.right, + bounds.height - insets.top - insets.bottom); } } --- /dev/null 2015-05-12 15:40:46.000000000 +0400 +++ new/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java 2015-05-12 15:40:46.000000000 +0400 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, 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.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; + +/** + * @test + * @bug 8065739 + * @summary [macosx] Frame warps to lower left of screen when displayed + * @author Alexandr Scherbatiy + */ +public class MaximizedToUnmaximized { + + public static void main(String[] args) throws Exception { + testFrame(false); + testFrame(true); + } + + static void testFrame(boolean isUndecorated) throws Exception { + Frame frame = new Frame(); + try { + Robot robot = new Robot(); + robot.setAutoDelay(100); + + frame.setUndecorated(isUndecorated); + GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getDefaultConfiguration(); + Rectangle bounds = gc.getBounds(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + int x = bounds.x + insets.left; + int y = bounds.y + insets.top; + int width = bounds.width - insets.left - insets.right; + int height = bounds.height - insets.top - insets.bottom; + Rectangle rect = new Rectangle(x, y, width, height); + frame.pack(); + frame.setBounds(rect); + frame.setVisible(true); + robot.waitForIdle(); + robot.delay(500); + + if (frame.getWidth() <= width / 2 + || frame.getHeight() <= height / 2) { + throw new RuntimeException("Frame size is small!"); + } + + if (!isUndecorated && frame.getExtendedState() != Frame.MAXIMIZED_BOTH) { + throw new RuntimeException("Frame state does not equal" + + " MAXIMIZED_BOTH!"); + } + } finally { + frame.dispose(); + } + } +} \ No newline at end of file --- /dev/null 2015-05-12 15:40:46.000000000 +0400 +++ new/test/java/awt/Frame/SetMaximizedBounds/MaximizedMovedWindow.java 2015-05-12 15:40:46.000000000 +0400 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015, 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.*; + +/* + * @test + * @bug 8065739 + * @summary Moved window is maximazed to new screen + * @author Alexandr Scherbatiy + * + * @run main MaximizedMovedWindow + */ +public class MaximizedMovedWindow { + + public static void main(String[] args) throws Exception { + + //Supported platforms are Windows and OS X. + String os = System.getProperty("os.name").toLowerCase(); + if (!os.contains("os x")) { + return; + } + + if (!Toolkit.getDefaultToolkit(). + isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { + return; + } + + GraphicsEnvironment ge = GraphicsEnvironment. + getLocalGraphicsEnvironment(); + + if (ge.isHeadlessInstance()) { + return; + } + + GraphicsDevice[] devices = ge.getScreenDevices(); + + if (devices.length < 2) { + return; + } + + Frame frame = null; + try { + + GraphicsConfiguration gc1 = devices[0].getDefaultConfiguration(); + GraphicsConfiguration gc2 = devices[1].getDefaultConfiguration(); + + Robot robot = new Robot(); + robot.setAutoDelay(50); + + frame = new Frame(); + Rectangle maxArea1 = getMaximizedScreenArea(gc1); + frame.setBounds(getSmallerRectangle(maxArea1)); + frame.setVisible(true); + robot.waitForIdle(); + + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + robot.waitForIdle(); + robot.delay(1000); + + Rectangle bounds = frame.getBounds(); + if (!bounds.equals(maxArea1)) { + throw new RuntimeException("The bounds of the Frame do not equal" + + " to screen 1 size"); + } + + frame.setExtendedState(Frame.NORMAL); + robot.waitForIdle(); + robot.delay(1000); + + Rectangle maxArea2 = getMaximizedScreenArea(gc2); + frame.setBounds(getSmallerRectangle(maxArea2)); + robot.waitForIdle(); + robot.delay(1000); + + frame.setExtendedState(Frame.MAXIMIZED_BOTH); + robot.waitForIdle(); + robot.delay(1000); + + bounds = frame.getBounds(); + if (!bounds.equals(maxArea2)) { + throw new RuntimeException("The bounds of the Frame do not equal" + + " to screen 2 size"); + } + } finally { + if (frame != null) { + frame.dispose(); + } + } + } + + static Rectangle getSmallerRectangle(Rectangle rect) { + return new Rectangle( + rect.x + rect.width / 6, + rect.y + rect.height / 6, + rect.width / 3, + rect.height / 3); + } + static Rectangle getMaximizedScreenArea(GraphicsConfiguration gc) { + Rectangle bounds = gc.getBounds(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + return new Rectangle( + bounds.x + insets.left, + bounds.y + insets.top, + bounds.width - insets.left - insets.right, + bounds.height - insets.top - insets.bottom); + } +}