7177173: [macosx] JFrame.setExtendedState(JFrame.MAXIMIZED_BOTH) not working as expected in JDK 7

Avoid unnecessary changes to the extended state

Reviewed-by: art, serb
This commit is contained in:
Anthony Petrov 2012-07-06 14:20:27 +04:00
parent e3a1dad2c0
commit d91b2b6f6e
2 changed files with 122 additions and 45 deletions

View file

@ -209,6 +209,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
private boolean undecorated; // initialized in getInitialStyleBits() private boolean undecorated; // initialized in getInitialStyleBits()
private Rectangle normalBounds = null; // not-null only for undecorated maximized windows private Rectangle normalBounds = null; // not-null only for undecorated maximized windows
private CPlatformResponder responder; private CPlatformResponder responder;
private volatile boolean zoomed = false; // from native perspective
public CPlatformWindow(final PeerType peerType) { public CPlatformWindow(final PeerType peerType) {
super(0, true); super(0, true);
@ -469,26 +470,42 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
nativeSetNSWindowBounds(getNSWindowPtr(), x, y, w, h); nativeSetNSWindowBounds(getNSWindowPtr(), x, y, w, h);
} }
private void zoom() { private boolean isMaximized() {
return undecorated ? this.normalBounds != null : zoomed;
}
private void maximize() {
if (isMaximized()) {
return;
}
if (!undecorated) { if (!undecorated) {
zoomed = true;
CWrapper.NSWindow.zoom(getNSWindowPtr()); CWrapper.NSWindow.zoom(getNSWindowPtr());
} else { } else {
// OS X handles -zoom incorrectly for undecorated windows deliverZoom(true);
final boolean isZoomed = this.normalBounds == null;
deliverZoom(isZoomed);
Rectangle toBounds; this.normalBounds = peer.getBounds();
if (isZoomed) { long screen = CWrapper.NSWindow.screen(getNSWindowPtr());
this.normalBounds = peer.getBounds(); Rectangle toBounds = CWrapper.NSScreen.visibleFrame(screen).getBounds();
long screen = CWrapper.NSWindow.screen(getNSWindowPtr()); // Flip the y coordinate
toBounds = CWrapper.NSScreen.visibleFrame(screen).getBounds(); Rectangle frame = CWrapper.NSScreen.frame(screen).getBounds();
// Flip the y coordinate toBounds.y = frame.height - toBounds.y - toBounds.height;
Rectangle frame = CWrapper.NSScreen.frame(screen).getBounds(); setBounds(toBounds.x, toBounds.y, toBounds.width, toBounds.height);
toBounds.y = frame.height - toBounds.y - toBounds.height; }
} else { }
toBounds = normalBounds;
this.normalBounds = null; private void unmaximize() {
} if (!isMaximized()) {
return;
}
if (!undecorated) {
zoomed = false;
CWrapper.NSWindow.zoom(getNSWindowPtr());
} else {
deliverZoom(false);
Rectangle toBounds = this.normalBounds;
this.normalBounds = null;
setBounds(toBounds.x, toBounds.y, toBounds.width, toBounds.height); setBounds(toBounds.x, toBounds.y, toBounds.width, toBounds.height);
} }
} }
@ -501,9 +518,9 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
public void setVisible(boolean visible) { public void setVisible(boolean visible) {
final long nsWindowPtr = getNSWindowPtr(); final long nsWindowPtr = getNSWindowPtr();
// 1. Process parent-child relationship when hiding // Process parent-child relationship when hiding
if (!visible) { if (!visible) {
// 1a. Unparent my children // Unparent my children
for (Window w : target.getOwnedWindows()) { for (Window w : target.getOwnedWindows()) {
WindowPeer p = (WindowPeer)w.getPeer(); WindowPeer p = (WindowPeer)w.getPeer();
if (p instanceof LWWindowPeer) { if (p instanceof LWWindowPeer) {
@ -514,30 +531,17 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
} }
} }
// 1b. Unparent myself // Unparent myself
if (owner != null && owner.isVisible()) { if (owner != null && owner.isVisible()) {
CWrapper.NSWindow.removeChildWindow(owner.getNSWindowPtr(), nsWindowPtr); CWrapper.NSWindow.removeChildWindow(owner.getNSWindowPtr(), nsWindowPtr);
} }
} }
// 2. Configure stuff // Configure stuff
updateIconImages(); updateIconImages();
updateFocusabilityForAutoRequestFocus(false); updateFocusabilityForAutoRequestFocus(false);
// 3. Manage the extended state when hiding // Actually show or hide the window
if (!visible) {
// Cancel out the current native state of the window
switch (peer.getState()) {
case Frame.ICONIFIED:
CWrapper.NSWindow.deminiaturize(nsWindowPtr);
break;
case Frame.MAXIMIZED_BOTH:
zoom();
break;
}
}
// 4. Actually show or hide the window
LWWindowPeer blocker = peer.getBlocker(); LWWindowPeer blocker = peer.getBlocker();
if (blocker == null || !visible) { if (blocker == null || !visible) {
// If it ain't blocked, or is being hidden, go regular way // If it ain't blocked, or is being hidden, go regular way
@ -566,16 +570,19 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
} }
this.visible = visible; this.visible = visible;
// 5. Manage the extended state when showing // Manage the extended state when showing
if (visible) { if (visible) {
// Re-apply the extended state as expected in shared code // Apply the extended state as expected in shared code
if (target instanceof Frame) { if (target instanceof Frame) {
switch (((Frame)target).getExtendedState()) { switch (((Frame)target).getExtendedState()) {
case Frame.ICONIFIED: case Frame.ICONIFIED:
CWrapper.NSWindow.miniaturize(nsWindowPtr); CWrapper.NSWindow.miniaturize(nsWindowPtr);
break; break;
case Frame.MAXIMIZED_BOTH: case Frame.MAXIMIZED_BOTH:
zoom(); maximize();
break;
default: // NORMAL
unmaximize(); // in case it was maximized, otherwise this is a no-op
break; break;
} }
} }
@ -583,12 +590,12 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr); nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr);
// 6. Configure stuff #2 // Configure stuff #2
updateFocusabilityForAutoRequestFocus(true); updateFocusabilityForAutoRequestFocus(true);
// 7. Manage parent-child relationship when showing // Manage parent-child relationship when showing
if (visible) { if (visible) {
// 7a. Add myself as a child // Add myself as a child
if (owner != null && owner.isVisible()) { if (owner != null && owner.isVisible()) {
CWrapper.NSWindow.addChildWindow(owner.getNSWindowPtr(), nsWindowPtr, CWrapper.NSWindow.NSWindowAbove); CWrapper.NSWindow.addChildWindow(owner.getNSWindowPtr(), nsWindowPtr, CWrapper.NSWindow.NSWindowAbove);
if (target.isAlwaysOnTop()) { if (target.isAlwaysOnTop()) {
@ -596,7 +603,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
} }
} }
// 7b. Add my own children to myself // Add my own children to myself
for (Window w : target.getOwnedWindows()) { for (Window w : target.getOwnedWindows()) {
WindowPeer p = (WindowPeer)w.getPeer(); WindowPeer p = (WindowPeer)w.getPeer();
if (p instanceof LWWindowPeer) { if (p instanceof LWWindowPeer) {
@ -611,7 +618,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
} }
} }
// 8. Deal with the blocker of the window being shown // Deal with the blocker of the window being shown
if (blocker != null && visible) { if (blocker != null && visible) {
// Make sure the blocker is above its siblings // Make sure the blocker is above its siblings
((CPlatformWindow)blocker.getPlatformWindow()).orderAboveSiblings(); ((CPlatformWindow)blocker.getPlatformWindow()).orderAboveSiblings();
@ -778,7 +785,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
if (prevWindowState == Frame.MAXIMIZED_BOTH) { if (prevWindowState == Frame.MAXIMIZED_BOTH) {
// let's return into the normal states first // let's return into the normal states first
// the zoom call toggles between the normal and the max states // the zoom call toggles between the normal and the max states
zoom(); unmaximize();
} }
CWrapper.NSWindow.miniaturize(nsWindowPtr); CWrapper.NSWindow.miniaturize(nsWindowPtr);
break; break;
@ -787,14 +794,14 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
// let's return into the normal states first // let's return into the normal states first
CWrapper.NSWindow.deminiaturize(nsWindowPtr); CWrapper.NSWindow.deminiaturize(nsWindowPtr);
} }
zoom(); maximize();
break; break;
case Frame.NORMAL: case Frame.NORMAL:
if (prevWindowState == Frame.ICONIFIED) { if (prevWindowState == Frame.ICONIFIED) {
CWrapper.NSWindow.deminiaturize(nsWindowPtr); CWrapper.NSWindow.deminiaturize(nsWindowPtr);
} else if (prevWindowState == Frame.MAXIMIZED_BOTH) { } else if (prevWindowState == Frame.MAXIMIZED_BOTH) {
// the zoom call toggles between the normal and the max states // the zoom call toggles between the normal and the max states
zoom(); unmaximize();
} }
break; break;
default: default:

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2012, 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.
*/
/*
@test
@bug 7177173
@summary The maximized state shouldn't be reset upon hiding a frame
@author anthony.petrov@oracle.com: area=awt.toplevel
@run main HideMaximized
*/
import java.awt.*;
public class HideMaximized {
public static void main(String[] args) {
if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
// Nothing to test
return;
}
// First test a decorated frame
Frame frame = new Frame("test");
test(frame);
// Now test an undecorated frames
frame = new Frame("undecorated test");
frame.setUndecorated(true);
test(frame);
}
private static void test(Frame frame) {
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
frame.setVisible(true);
try { Thread.sleep(1000); } catch (Exception ex) {}
if (frame.getExtendedState() != Frame.MAXIMIZED_BOTH) {
throw new RuntimeException("The maximized state has not been applied");
}
// This will hide the frame, and also clean things up for safe exiting
frame.dispose();
try { Thread.sleep(1000); } catch (Exception ex) {}
if (frame.getExtendedState() != Frame.MAXIMIZED_BOTH) {
throw new RuntimeException("The maximized state has been reset");
}
}
}