8065739: [macosx] Frame warps to lower left of screen when
7124365: [macosx] setMaximizedBounds() should be implemented
Reviewed-by: serb, azvegint
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java Wed May 20 17:10:15 2015 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java Fri May 22 15:19:05 2015 +0400
@@ -61,6 +61,7 @@
private static final int MINIMUM_HEIGHT = 1;
private Insets insets = new Insets(0, 0, 0, 0);
+ private Rectangle maximizedBounds;
private GraphicsDevice graphicsDevice;
private GraphicsConfiguration graphicsConfig;
@@ -176,8 +177,10 @@
if (getTarget() instanceof Frame) {
- setTitle(((Frame) getTarget()).getTitle());
- setState(((Frame) getTarget()).getExtendedState());
+ Frame frame = (Frame) getTarget();
+ setTitle(frame.getTitle());
+ setState(frame.getExtendedState());
+ setMaximizedBounds(frame.getMaximizedBounds());
} else if (getTarget() instanceof Dialog) {
setTitle(((Dialog) getTarget()).getTitle());
}
@@ -543,9 +546,40 @@
return windowState;
}
+ private boolean isMaximizedBoundsSet() {
+ synchronized (getStateLock()) {
+ return maximizedBounds != null;
+ }
+ }
+
+ private Rectangle getDefaultMaximizedBounds() {
+ GraphicsConfiguration config = getGraphicsConfiguration();
+ Insets screenInsets = ((CGraphicsDevice) config.getDevice())
+ .getScreenInsets();
+ Rectangle gcBounds = config.getBounds();
+ return new Rectangle(
+ gcBounds.x + screenInsets.left,
+ gcBounds.y + screenInsets.top,
+ gcBounds.width - screenInsets.left - screenInsets.right,
+ gcBounds.height - screenInsets.top - screenInsets.bottom);
+ }
+
@Override
public void setMaximizedBounds(Rectangle bounds) {
- // TODO: not implemented
+ boolean isMaximizedBoundsSet;
+ synchronized (getStateLock()) {
+ this.maximizedBounds = (isMaximizedBoundsSet = (bounds != null))
+ ? constrainBounds(bounds) : null;
+ }
+
+ setPlatformMaximizedBounds(isMaximizedBoundsSet ? maximizedBounds
+ : getDefaultMaximizedBounds());
+ }
+
+ private void setPlatformMaximizedBounds(Rectangle bounds) {
+ platformWindow.setMaximizedBounds(
+ bounds.x, bounds.y,
+ bounds.width, bounds.height);
}
@Override
@@ -635,6 +669,10 @@
// Second, update the graphics config and surface data
final boolean isNewDevice = updateGraphicsDevice();
+ if (isNewDevice && !isMaximizedBoundsSet()) {
+ setPlatformMaximizedBounds(getDefaultMaximizedBounds());
+ }
+
if (resized || isNewDevice) {
replaceSurfaceData();
updateMinimumSize();
@@ -1055,6 +1093,9 @@
public final void displayChanged() {
if (updateGraphicsDevice()) {
updateMinimumSize();
+ if (!isMaximizedBoundsSet()) {
+ setPlatformMaximizedBounds(getDefaultMaximizedBounds());
+ }
}
// Replace surface unconditionally, because internal state of the
// GraphicsDevice could be changed.
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java Wed May 20 17:10:15 2015 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java Fri May 22 15:19:05 2015 +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();
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed May 20 17:10:15 2015 +0300
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri May 22 15:19:05 2015 +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);
@@ -474,6 +476,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());
@@ -979,13 +985,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);
}
}
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h Wed May 20 17:10:15 2015 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.h Fri May 22 15:19:05 2015 +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
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m Wed May 20 17:10:15 2015 +0300
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m Fri May 22 15:19:05 2015 +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
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/MaximizedToUnmaximized/MaximizedToUnmaximized.java Fri May 22 15:19:05 2015 +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 Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/SetMaximizedBounds/MaximizedMovedWindow.java Fri May 22 15:19:05 2015 +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);
+ }
+}
--- a/jdk/test/java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java Wed May 20 17:10:15 2015 +0300
+++ b/jdk/test/java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java Fri May 22 15:19:05 2015 +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 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;
+ }
- public void doTest() throws Exception {
- robot = new ExtendedRobot();
+ GraphicsEnvironment ge = GraphicsEnvironment.
+ getLocalGraphicsEnvironment();
+
+ if (ge.isHeadlessInstance()) {
+ return;
+ }
+
+ for (GraphicsDevice gd : ge.getScreenDevices()) {
+ for (GraphicsConfiguration gc : gd.getConfigurations()) {
+ testMaximizedBounds(gc);
+ }
+ }
+ }
- EventQueue.invokeAndWait( () -> {
- frame = new Frame( "TestFrame ");
- frame.setLayout(new FlowLayout());
+ static void testMaximizedBounds(GraphicsConfiguration gc) throws Exception {
+
+ Frame frame = null;
+ try {
+
+ Rectangle maxArea = getMaximizedScreenArea(gc);
+
+ Robot robot = new Robot();
+ robot.setAutoDelay(50);
- if (Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
- supported = true;
- frame.setMaximizedBounds(max);
- } else {
- supported = false;
+ 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);
+
+ 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");
}
- frame.setSize(200, 200);
- frame.setVisible(true);
- });
+ frame.setExtendedState(Frame.NORMAL);
+ 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))
+ 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);
+
+ 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");
+ }
+ } finally {
+ if (frame != null) {
+ frame.dispose();
+ }
}
-
- 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);
}
}