8165619: Frame is not repainted if created in state=MAXIMIZED_BOTH on Unity
authorssadetsky
Mon, 03 Oct 2016 18:51:49 +0300
changeset 41409 04b42eb73ee6
parent 41408 9bc553d242eb
child 41410 ef26c8e40f1e
8165619: Frame is not repainted if created in state=MAXIMIZED_BOTH on Unity Reviewed-by: azvegint
jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java
jdk/test/java/awt/Frame/DecoratedFrameInsets/DecoratedFrameInsetsTest.java
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java	Fri Sep 30 22:10:44 2016 +0300
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java	Mon Oct 03 18:51:49 2016 +0300
@@ -308,6 +308,19 @@
         super.handlePropertyNotify(xev);
 
         XPropertyEvent ev = xev.get_xproperty();
+        if( !insets_corrected && isReparented() &&
+                                         XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
+            int state = XWM.getWM().getState(this);
+            if ((state & Frame.MAXIMIZED_BOTH) ==  Frame.MAXIMIZED_BOTH) {
+                // Stop ignoring ConfigureNotify because no extents will be sent
+                // by WM for initially maximized decorated window.
+                // Re-request window bounds to ensure actual dimensions and
+                // notify the target with the initial size.
+                insets_corrected = true;
+                XlibWrapper.XConfigureWindow(XToolkit.getDisplay(),
+                                                             getWindow(), 0, 0);
+            }
+        }
         if (ev.get_atom() == XWM.XA_KDE_NET_WM_FRAME_STRUT.getAtom()
             || ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom())
         {
@@ -325,11 +338,30 @@
                 if (!isEmbedded() && !isTargetUndecorated()) {
                     lastKnownInsets.put(getClass(), in);
                 }
-                if (!in.equals(dimensions.getInsets()) ||
-                                                !dimensions.isClientSizeSet()) {
-                    handleCorrectInsets(in);
+                if (!in.equals(dimensions.getInsets())) {
+                    if (insets_corrected || isMaximized()) {
+                        currentInsets = in;
+                        insets_corrected = true;
+                        // insets were changed by WM. To handle this situation
+                        // re-request window bounds because the current
+                        // dimensions may be not actual as well.
+                        XlibWrapper.XConfigureWindow(XToolkit.getDisplay(),
+                                                             getWindow(), 0, 0);
+                    } else {
+                        // recalculate dimensions when window is just created
+                        // and the initially guessed insets were wrong
+                        handleCorrectInsets(in);
+                    }
+                } else if (!dimensions.isClientSizeSet()) {
+                    insets_corrected = true;
+                    // initial insets were guessed correctly. Re-request
+                    // frame bounds because they may be changed by WM if the
+                    // initial window position overlapped desktop's toolbars.
+                    // This should initiate the final ConfigureNotify upon which
+                    // the target will be notified with the final size.
+                    XlibWrapper.XConfigureWindow(XToolkit.getDisplay(),
+                                                             getWindow(), 0, 0);
                 }
-                insets_corrected = true;
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/DecoratedFrameInsets/DecoratedFrameInsetsTest.java	Mon Oct 03 18:51:49 2016 +0300
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, 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 8165619
+ * @summary Frame is not repainted if created in state=MAXIMIZED_BOTH on Unity
+ * @run main DecoratedFrameInsetsTest
+ */
+
+import java.awt.*;
+
+public class DecoratedFrameInsetsTest {
+    static Robot robot;
+    private static Insets expectedInsets;
+
+    public static void main(String[] args) throws Exception {
+        robot = new Robot();
+        expectedInsets = getExpectedInsets();
+        System.out.println("Normal state insets: " + expectedInsets);
+        testState(Frame.MAXIMIZED_BOTH);
+        testState(Frame.ICONIFIED);
+        testState(Frame.MAXIMIZED_HORIZ);
+        testState(Frame.MAXIMIZED_VERT);
+    }
+
+    private static Insets getExpectedInsets() {
+        Frame frame = new Frame();
+        frame.setVisible(true);
+        robot.waitForIdle();
+        robot.delay(200);
+        Insets expectedInsets = frame.getInsets();
+        frame.dispose();
+        return expectedInsets;
+    }
+
+    static void testState(int state) {
+        Frame frame = new Frame();
+        if( Toolkit.getDefaultToolkit().isFrameStateSupported(state)) {
+            frame.setBounds(150, 150, 200, 200);
+            frame.setExtendedState(state);
+            frame.setVisible(true);
+            robot.waitForIdle();
+            robot.delay(200);
+            System.out.println("State " + state +
+                                               " insets: " + frame.getInsets());
+
+            frame.setExtendedState(Frame.NORMAL);
+            frame.toFront();
+            robot.waitForIdle();
+            robot.delay(200);
+            Insets insets = frame.getInsets();
+            frame.dispose();
+            System.out.println("State " + state +
+                                           " back to normal insets: " + insets);
+            if(!expectedInsets.equals(insets)) {
+                throw new RuntimeException("Insets are wrong " + insets);
+            }
+        }
+    }
+}