8209123: [Macosx] Maximized frame (frame state set to MAXIMIZED_BOTH using setExtendedState) is resizable on Mac but not on Windows and Ubuntu
authormhalder
Tue, 27 Nov 2018 13:47:31 +0530
changeset 52757 3c4c1debe32c
parent 52756 0d757a37896c
child 52758 b2e14d91a50c
8209123: [Macosx] Maximized frame (frame state set to MAXIMIZED_BOTH using setExtendedState) is resizable on Mac but not on Windows and Ubuntu Reviewed-by: kaddepalli, psadhukhan
src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Tue Nov 27 10:59:24 2018 +0530
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Tue Nov 27 13:47:31 2018 +0530
@@ -295,6 +295,8 @@
     private Rectangle normalBounds = null; // not-null only for undecorated maximized windows
     private CPlatformResponder responder;
     private long lastBecomeMainTime; // this is necessary to preserve right siblings order
+    private boolean maximizedBothState = false;
+    private boolean frameResizibilityChanged = false;
 
     public CPlatformWindow() {
         super(0, true);
@@ -397,7 +399,7 @@
 
         // Either java.awt.Frame or java.awt.Dialog can be resizable, however java.awt.Window is never resizable
         {
-            final boolean resizable = isFrame ? ((Frame)target).isResizable() : (isDialog ? ((Dialog)target).isResizable() : false);
+            final boolean resizable = isTargetResizable();
             styleBits = SET(styleBits, RESIZABLE, resizable);
             if (!resizable) {
                 styleBits = SET(styleBits, ZOOMABLE, false);
@@ -609,6 +611,8 @@
             setBounds(maximizedBounds.x, maximizedBounds.y,
                     maximizedBounds.width, maximizedBounds.height);
         }
+        setFrameResizibilityChanged(true);
+        updateResizableAndMaximizeState(true);
     }
 
     private void unmaximize() {
@@ -705,11 +709,9 @@
         // Manage the extended state when showing
         if (visible) {
             /* Frame or Dialog should be set property WINDOW_FULLSCREENABLE to true if the
-            Frame or Dialog is resizable.
+            Frame resizable and Frame state is not MAXIMIZED_BOTH or Dialog is resizable.
             **/
-            final boolean resizable = (target instanceof Frame) ? ((Frame)target).isResizable() :
-            ((target instanceof Dialog) ? ((Dialog)target).isResizable() : false);
-            if (resizable) {
+            if (isTargetResizable()) {
                 setCanFullscreen(true);
             }
 
@@ -724,6 +726,12 @@
                         // Treat all state bit masks with ICONIFIED bit as ICONIFIED state.
                         frameState = Frame.ICONIFIED;
                     }
+
+                    if (isFrameResizibilityChanged()) {
+                        updateResizableAndMaximizeState(false);
+                        setFrameResizibilityChanged(false);
+                    }
+
                     switch (frameState) {
                         case Frame.ICONIFIED:
                             execute(CWrapper.NSWindow::miniaturize);
@@ -843,9 +851,10 @@
 
     @Override
     public void setResizable(final boolean resizable) {
-        setCanFullscreen(resizable);
-        setStyleBits(RESIZABLE, resizable);
-        setStyleBits(ZOOMABLE, resizable);
+        boolean windowResizable = resizable && !isMaximizedBoth();
+        setCanFullscreen(windowResizable);
+        setStyleBits(RESIZABLE, windowResizable);
+        setStyleBits(ZOOMABLE, windowResizable);
     }
 
     @Override
@@ -953,6 +962,12 @@
             // Treat all state bit masks with ICONIFIED bit as ICONIFIED state.
             windowState = Frame.ICONIFIED;
         }
+
+        if (isFrameResizibilityChanged()) {
+            updateResizableAndMaximizeState(false);
+            setFrameResizibilityChanged(false);
+        }
+
         switch (windowState) {
             case Frame.ICONIFIED:
                 if (prevWindowState == Frame.MAXIMIZED_BOTH) {
@@ -1156,6 +1171,21 @@
     }
 
     /*
+     * Resizibility of frame with state MAXIMIZED_BOTH is set to true to zoom
+     * the frame on double click on title bar and set to false later. This is
+     * required as frame won't zoom if resizibility of frame is false.
+     */
+    private void deliverDoubleClickOnTitlebar() {
+        if ((peer != null) && (target instanceof Frame)) {
+            if (isMaximizedBoth()) {
+                updateResizableAndMaximizeState(false);
+                execute(CWrapper.NSWindow::zoom);
+                updateResizableAndMaximizeState(true);
+            }
+        }
+    }
+
+    /*
      * Our focus model is synthetic and only non-simple window
      * may become natively focusable window.
      */
@@ -1330,6 +1360,32 @@
         return false;
     }
 
+    private boolean isTargetResizable() {
+        if (target instanceof Frame) {
+            return ((Frame)target).isResizable() && !isMaximizedBoth();
+        } else if (target instanceof Dialog) {
+            return ((Dialog)target).isResizable();
+        }
+        return false;
+    }
+
+    private void updateResizableAndMaximizeState(boolean maximizeState) {
+        maximizedBothState = maximizeState;
+        setResizable(!maximizeState);
+    }
+
+    private boolean isMaximizedBoth() {
+        return maximizedBothState;
+    }
+
+    private void setFrameResizibilityChanged(boolean resize) {
+        frameResizibilityChanged = resize;
+    }
+
+    private boolean isFrameResizibilityChanged() {
+        return frameResizibilityChanged;
+    }
+
     // ----------------------------------------------------------------------
     //                          NATIVE CALLBACKS
     // ----------------------------------------------------------------------
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m	Tue Nov 27 10:59:24 2018 +0530
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m	Tue Nov 27 13:47:31 2018 +0530
@@ -965,6 +965,11 @@
                     // Currently, no need to deliver the whole NSEvent.
                     static JNF_MEMBER_CACHE(jm_deliverNCMouseDown, jc_CPlatformWindow, "deliverNCMouseDown", "()V");
                     JNFCallVoidMethod(env, platformWindow, jm_deliverNCMouseDown);
+                    // Deliver double click on title bar
+                    if ([event clickCount] > 1) {
+                        static JNF_MEMBER_CACHE(jm_deliverDoubleClickOnTitlebar, jc_CPlatformWindow, "deliverDoubleClickOnTitlebar", "()V");
+                        JNFCallVoidMethod(env, platformWindow, jm_deliverDoubleClickOnTitlebar);
+                    }
                     (*env)->DeleteLocalRef(env, platformWindow);
                 }
             }