8065739: [macosx] Frame warps to lower left of screen when

7124365: [macosx] setMaximizedBounds() should be implemented

Reviewed-by: serb, azvegint
This commit is contained in:
Alexander Scherbatiy 2015-05-22 15:19:05 +04:00
parent fc00fd2ffb
commit 83dcd68033
8 changed files with 387 additions and 58 deletions

View File

@ -61,6 +61,7 @@ public class LWWindowPeer
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 @@ public class LWWindowPeer
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 @@ public class LWWindowPeer
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 @@ public class LWWindowPeer
// 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 class LWWindowPeer
public final void displayChanged() {
if (updateGraphicsDevice()) {
updateMinimumSize();
if (!isMaximizedBoundsSet()) {
setPlatformMaximizedBounds(getDefaultMaximizedBounds());
}
}
// Replace surface unconditionally, because internal state of the
// GraphicsDevice could be changed.

View File

@ -66,6 +66,11 @@ public interface PlatformWindow {
*/
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.
*/

View File

@ -51,6 +51,8 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
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 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
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 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
}
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);
}
}

View File

@ -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

View File

@ -184,6 +184,7 @@ AWT_NS_WINDOW_IMPLEMENTATION
@synthesize isEnabled;
@synthesize ownerWindow;
@synthesize preFullScreenLevel;
@synthesize standardFrame;
- (void) updateMinMaxSize:(BOOL)resizable {
if (resizable) {
@ -509,6 +510,12 @@ AWT_ASSERT_APPKIT_THREAD;
// window exposing in _setVisible:(BOOL)
}
- (NSRect)windowWillUseStandardFrame:(NSWindow *)window
defaultFrame:(NSRect)newFrame {
return [self standardFrame];
}
- (void) _deliverIconify:(BOOL)iconify {
AWT_ASSERT_APPKIT_THREAD;
@ -951,6 +958,30 @@ JNF_COCOA_ENTER(env);
JNF_COCOA_EXIT(env);
}
/*
* 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

View File

@ -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();
}
}
}

View File

@ -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);
}
}

View File

@ -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 {
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;
}
frame.setSize(200, 200);
frame.setVisible(true);
});
robot.waitForIdle(2000);
if (supported) {
EventQueue.invokeAndWait( () -> {
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
});
robot.waitForIdle(2000);
bound = frame.getBounds();
if(!bound.equals(max))
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");
//Supported platforms are Windows and OS X.
String os = System.getProperty("os.name").toLowerCase();
if (!os.contains("windows") && !os.contains("os x")) {
return;
}
frame.dispose();
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);
}
}
}
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 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);
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.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);
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();
}
}
}
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);
}
}