JDK-7124428 : [macosx] Frame.setExtendedState() doesn't work for undecorated windows
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: os_x
  • CPU: generic
  • Submitted: 2011-12-23
  • Updated: 2013-07-12
  • Resolved: 2012-04-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u4 b18Fixed 8Fixed
Related Reports
Relates :  
Description
http://java.net/jira/browse/MACOSX_PORT-35 submitted 2011/04/27 by Artem Ananiev
Run the attached test. It creates a simple undecorated window and register a mouse listener. When clicked, the window is maximized with a call to setExtendedState(MAXIMIZED_BOTH). However, the maximization only works for decorated windows, while undecorated windows just move to the left bottom corner of the screen.
The test case:

import java.awt.*;
import java.awt.event.*;

public class CheckExtendedState {

    public static void main(String[] args) {

	final Frame f = new Frame();
	f.setUndecorated(true);
	f.addMouseListener(new MouseAdapter() {
	    public void mouseClicked(MouseEvent e) {
		f.setExtendedState(Frame.MAXIMIZED_BOTH);
	    }
	});
	f.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
		if (e.getKeyChar() == 'g') {
		    System.exit(0);
		}
	    }
	});
	f.setSize(640, 480);
	f.setLocationRelativeTo(null);
	f.setVisible(true);
    }

}

Comments
SUGGESTED FIX --- old/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2012-03-16 21:15:09.000000000 +0400 +++ new/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2012-03-16 21:15:09.000000000 +0400 @@ -203,6 +203,8 @@ private LWWindowPeer peer; private CPlatformView contentView; private CPlatformWindow owner; + private boolean undecorated; // initialized in getInitialStyleBits() + private Rectangle normalBounds = null; // not-null only for undecorated maximized windows public CPlatformWindow(final PeerType peerType) { super(0, true); @@ -281,8 +283,8 @@ // Either java.awt.Frame or java.awt.Dialog can be undecorated, however java.awt.Window always is undecorated. { - final boolean undecorated = isFrame ? ((Frame)target).isUndecorated() : (isDialog ? ((Dialog)target).isUndecorated() : true); - if (undecorated) styleBits = SET(styleBits, DECORATED, false); + this.undecorated = isFrame ? ((Frame)target).isUndecorated() : (isDialog ? ((Dialog)target).isUndecorated() : true); + if (this.undecorated) styleBits = SET(styleBits, DECORATED, false); } // Either java.awt.Frame or java.awt.Dialog can be resizable, however java.awt.Window is never resizable @@ -468,6 +470,30 @@ nativeSetNSWindowBounds(getNSWindowPtr(), x, y, w, h); } + private void zoom() { + if (!undecorated) { + CWrapper.NSWindow.zoom(getNSWindowPtr()); + } else { + // OS X handles -zoom incorrectly for undecorated windows + final boolean isZoomed = this.normalBounds == null; + deliverZoom(isZoomed); + + Rectangle toBounds; + if (isZoomed) { + this.normalBounds = peer.getBounds(); + long screen = CWrapper.NSWindow.screen(getNSWindowPtr()); + toBounds = CWrapper.NSScreen.visibleFrame(screen).getBounds(); + // Flip the y coordinate + Rectangle frame = CWrapper.NSScreen.frame(screen).getBounds(); + toBounds.y = frame.height - toBounds.y - toBounds.height; + } else { + toBounds = normalBounds; + this.normalBounds = null; + } + setBounds(toBounds.x, toBounds.y, toBounds.width, toBounds.height); + } + } + @Override // PlatformWindow public void setVisible(boolean visible) { final long nsWindowPtr = getNSWindowPtr(); @@ -488,7 +514,7 @@ CWrapper.NSWindow.deminiaturize(nsWindowPtr); break; case Frame.MAXIMIZED_BOTH: - CWrapper.NSWindow.zoom(nsWindowPtr); + zoom(); break; } } @@ -521,7 +547,7 @@ CWrapper.NSWindow.miniaturize(nsWindowPtr); break; case Frame.MAXIMIZED_BOTH: - CWrapper.NSWindow.zoom(nsWindowPtr); + zoom(); break; } } @@ -682,7 +708,7 @@ if (prevWindowState == Frame.MAXIMIZED_BOTH) { // let's return into the normal states first // the zoom call toggles between the normal and the max states - CWrapper.NSWindow.zoom(nsWindowPtr); + zoom(); } CWrapper.NSWindow.miniaturize(nsWindowPtr); break; @@ -691,14 +717,14 @@ // let's return into the normal states first CWrapper.NSWindow.deminiaturize(nsWindowPtr); } - CWrapper.NSWindow.zoom(nsWindowPtr); + zoom(); break; case Frame.NORMAL: if (prevWindowState == Frame.ICONIFIED) { CWrapper.NSWindow.deminiaturize(nsWindowPtr); } else if (prevWindowState == Frame.MAXIMIZED_BOTH) { // the zoom call toggles between the normal and the max states - CWrapper.NSWindow.zoom(nsWindowPtr); + zoom(); } break; default:
16-03-2012

EVALUATION It looks like OS X handles the -zoom request incorrectly for undecorated windows. Therefore we have to emulate it in our code.
16-03-2012

EVALUATION Author: Yuri Nesterenko Date: 14/Oct/11 09:15 AM Build: b201 AWT_ZoomFrame/Automated/UndecoratedFrame/GetStateTest/GetStateTest.html AWT_UndecoratedFrame/Automated/AWT/FullSize AWT_UndecoratedFrame/Automated/Swing/FullSize closed/java/awt/Frame/Undecorated/MaximizeUndecoratedTest/MaximizeUndecoratedTest
23-12-2011