changeset 5386:5b74dcc8191d

7177173: [macosx] JFrame.setExtendedState(JFrame.MAXIMIZED_BOTH) not working as expected in JDK 7 Summary: Apply the extended state only when needed Reviewed-by: art, serb
author anthony
date Wed, 11 Jul 2012 13:46:50 +0400
parents 38d2807c7801
children dcee29cd4b80
files src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java test/java/awt/Frame/HideMaximized/HideMaximized.java
diffstat 2 files changed, 122 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Thu Jun 28 16:12:58 2012 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Jul 11 13:46:50 2012 +0400
@@ -209,6 +209,7 @@
     private boolean undecorated; // initialized in getInitialStyleBits()
     private Rectangle normalBounds = null; // not-null only for undecorated maximized windows
     private CPlatformResponder responder;
+    private volatile boolean zoomed = false; // from native perspective
 
     public CPlatformWindow(final PeerType peerType) {
         super(0, true);
@@ -471,26 +472,42 @@
         return this.visible;
     }
 
-    private void zoom() {
+    private boolean isMaximized() {
+        return undecorated ? this.normalBounds != null : zoomed;
+    }
+
+    private void maximize() {
+        if (isMaximized()) {
+            return;
+        }
         if (!undecorated) {
+            zoomed = true;
             CWrapper.NSWindow.zoom(getNSWindowPtr());
         } else {
-            // OS X handles -zoom incorrectly for undecorated windows
-            final boolean isZoomed = this.normalBounds == null;
-            deliverZoom(isZoomed);
+            deliverZoom(true);
 
-            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;
-            }
+            this.normalBounds = peer.getBounds();
+            long screen = CWrapper.NSWindow.screen(getNSWindowPtr());
+            Rectangle 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;
+            setBounds(toBounds.x, toBounds.y, toBounds.width, toBounds.height);
+        }
+    }
+
+    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);
         }
     }
@@ -499,9 +516,9 @@
     public void setVisible(boolean visible) {
         final long nsWindowPtr = getNSWindowPtr();
 
-        // 1. Process parent-child relationship when hiding
+        // Process parent-child relationship when hiding
         if (!visible) {
-            // 1a. Unparent my children
+            // Unparent my children
             for (Window w : target.getOwnedWindows()) {
                 WindowPeer p = (WindowPeer)w.getPeer();
                 if (p instanceof LWWindowPeer) {
@@ -512,30 +529,17 @@
                 }
             }
 
-            // 1b. Unparent myself
+            // Unparent myself
             if (owner != null && owner.isVisible()) {
                 CWrapper.NSWindow.removeChildWindow(owner.getNSWindowPtr(), nsWindowPtr);
             }
         }
 
-        // 2. Configure stuff
+        // Configure stuff
         updateIconImages();
         updateFocusabilityForAutoRequestFocus(false);
 
-        // 3. Manage the extended state when hiding
-        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
+        // Actually show or hide the window
         LWWindowPeer blocker = peer.getBlocker();
         if (blocker == null || !visible) {
             // If it ain't blocked, or is being hidden, go regular way
@@ -564,16 +568,19 @@
         }
         this.visible = visible;
 
-        // 5. Manage the extended state when showing
+        // Manage the extended state when showing
         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) {
                 switch (((Frame)target).getExtendedState()) {
                     case Frame.ICONIFIED:
                         CWrapper.NSWindow.miniaturize(nsWindowPtr);
                         break;
                     case Frame.MAXIMIZED_BOTH:
-                        zoom();
+                        maximize();
+                        break;
+                    default: // NORMAL
+                        unmaximize(); // in case it was maximized, otherwise this is a no-op
                         break;
                 }
             }
@@ -581,12 +588,12 @@
 
         nativeSynthesizeMouseEnteredExitedEvents(nsWindowPtr);
 
-        // 6. Configure stuff #2
+        // Configure stuff #2
         updateFocusabilityForAutoRequestFocus(true);
 
-        // 7. Manage parent-child relationship when showing
+        // Manage parent-child relationship when showing
         if (visible) {
-            // 7a. Add myself as a child
+            // Add myself as a child
             if (owner != null && owner.isVisible()) {
                 CWrapper.NSWindow.addChildWindow(owner.getNSWindowPtr(), nsWindowPtr, CWrapper.NSWindow.NSWindowAbove);
                 if (target.isAlwaysOnTop()) {
@@ -594,7 +601,7 @@
                 }
             }
 
-            // 7b. Add my own children to myself
+            // Add my own children to myself
             for (Window w : target.getOwnedWindows()) {
                 WindowPeer p = (WindowPeer)w.getPeer();
                 if (p instanceof LWWindowPeer) {
@@ -609,7 +616,7 @@
             }
         }
 
-        // 8. Deal with the blocker of the window being shown
+        // Deal with the blocker of the window being shown
         if (blocker != null && visible) {
             // Make sure the blocker is above its siblings
             ((CPlatformWindow)blocker.getPlatformWindow()).orderAboveSiblings();
@@ -767,7 +774,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
-                    zoom();
+                    unmaximize();
                 }
                 CWrapper.NSWindow.miniaturize(nsWindowPtr);
                 break;
@@ -776,14 +783,14 @@
                     // let's return into the normal states first
                     CWrapper.NSWindow.deminiaturize(nsWindowPtr);
                 }
-                zoom();
+                maximize();
                 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
-                    zoom();
+                    unmaximize();
                 }
                 break;
             default:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/Frame/HideMaximized/HideMaximized.java	Wed Jul 11 13:46:50 2012 +0400
@@ -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");
+        }
+    }
+}