# HG changeset patch
# User Denis Lila <dlila@redhat.com>
# Date 1305642927 14400
# Node ID 49098163596b4e2972ddad36550e0b9801d3170b
# Parent  cf7c64f276c60d1bab5b26b87a4e337dadbb4888
Add mutter as a window manager.

diff -r cf7c64f276c6 -r 49098163596b src/solaris/classes/sun/awt/X11/XDecoratedPeer.java
--- openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java	Wed May 11 11:08:03 2011 -0400
+++ openjdk/jdk/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java	Tue May 17 10:35:27 2011 -0400
@@ -721,7 +721,7 @@
             // Location, Client size + insets
             newLocation = new Point(xe.get_x() - currentInsets.left, xe.get_y() - currentInsets.top);
         } else {
-            // CDE/MWM/Metacity/Sawfish bug: if shell is resized using
+            // CDE/MWM/Metacity/Sawfish/Mutter bug: if shell is resized using
             // top or left border, we don't receive synthetic
             // ConfigureNotify, only the one from X with zero
             // coordinates.  This is the workaround to get real
@@ -731,6 +731,7 @@
                 case XWM.MOTIF_WM:
                 case XWM.METACITY_WM:
                 case XWM.SAWFISH_WM:
+                case XWM.MUTTER_WM:
                 {
                     Point xlocation = queryXLocation();
                     if (log.isLoggable(PlatformLogger.FINE)) log.fine("New X location: {0}", xlocation);
diff -r cf7c64f276c6 -r 49098163596b src/solaris/classes/sun/awt/X11/XWM.java
--- openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XWM.java	Wed May 11 11:08:03 2011 -0400
+++ openjdk/jdk/src/solaris/classes/sun/awt/X11/XWM.java	Tue May 17 10:35:27 2011 -0400
@@ -101,7 +101,8 @@
         ICE_WM = 10,
         METACITY_WM = 11,
         COMPIZ_WM = 12,
-        LG3D_WM = 13;
+        LG3D_WM = 13,
+        MUTTER_WM = 14;
     public String toString() {
         switch  (WMID) {
           case NO_WM:
@@ -128,6 +129,8 @@
               return "Compiz";
           case LG3D_WM:
               return "LookingGlass";
+          case MUTTER_WM:
+              return "Mutter";
           case UNDETERMINED_WM:
           default:
               return "Undetermined WM";
@@ -566,6 +569,12 @@
 //                            getIntProperty(XToolkit.getDefaultRootWindow(), XAtom.XA_CARDINAL)) == 0);
     }
 
+    static boolean isMutter() {
+        return isNetWMName("Mutter");
+    }
+
+    // TODO: according to wikipedia, compiz is now reparenting. This should
+    // probably be updated.
     static boolean isNonReparentingWM() {
         return (XWM.getWMID() == XWM.COMPIZ_WM || XWM.getWMID() == XWM.LG3D_WM);
     }
@@ -735,10 +744,12 @@
                 awt_wmgr = XWM.ENLIGHTEN_WM;
             } else if (isMetacity()) {
                 awt_wmgr = XWM.METACITY_WM;
+            } else if (isMutter()) {
+                awt_wmgr = XWM.MUTTER_WM;
             } else if (isSawfish()) {
                 awt_wmgr = XWM.SAWFISH_WM;
             } else if (isKDE2()) {
-                awt_wmgr =XWM.KDE2_WM;
+                awt_wmgr = XWM.KDE2_WM;
             } else if (isCompiz()) {
                 awt_wmgr = XWM.COMPIZ_WM;
             } else if (isLookingGlass()) {
@@ -1036,6 +1047,8 @@
 
     boolean supportsDynamicLayout() {
         int wm = getWMID();
+        // TODO: does mutter support this? It's a fancy new WM, so it probably
+        // does. Confirm and fix this.
         switch (wm) {
           case XWM.ENLIGHTEN_WM:
           case XWM.KDE2_WM:
@@ -1360,6 +1373,7 @@
                 return insets;
             }
         }
+        // TODO: figure out if Mutter implements the insets property.
         switch(getWMID()) {
           case XWM.KDE2_WM:
               return getInsetsFromProp(window, XA_KDE_NET_WM_FRAME_STRUT);
@@ -1554,6 +1568,9 @@
                       correctWM.bottom = correctWM.left;
                       break;
                   }
+                  case XWM.MUTTER_WM:
+                      // TODO: Figure out if Mutter is double reparenting.
+                      // For now the fallback code is good enough.
                   case XWM.OTHER_WM:
                   default: {                /* this is very similar to the E! case above */
                       insLog.finest("Getting correct insets for OTHER_WM/default, parent: {0}", parent);
diff -r cf7c64f276c6 -r 49098163596b test/java/awt/WMSpecificTests/Mutter/MutterMaximizeTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ openjdk/jdk/test/java/awt/WMSpecificTests/Mutter/MutterMaximizeTest.java	Tue May 17 10:35:27 2011 -0400
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2011 Red Hat, Inc.  All Rights Reserved.
+ * Copyright (c) 2011, 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      7043963
+  @summary  Tests  that the screen location of windows is
+            updated properly after a maximize.
+  @author   Denis Lila
+  @library  ../../regtesthelpers
+  @build    Util
+  @run      main MutterMaximizeTest
+*/
+
+import java.awt.AWTException;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.Window;
+import java.awt.event.InputEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import test.java.awt.regtesthelpers.Util;
+
+@SuppressWarnings("serial")
+public class MutterMaximizeTest extends Frame {
+
+    public static void main(String[] args) throws InterruptedException {
+        if (Util.getWMID() != Util.MUTTER_WM) {
+            System.out.println("This test is only useful on Mutter");
+            return;
+        }
+        MutterMaximizeTest frame = new MutterMaximizeTest();
+        frame.addWindowListener(Util.getClosingWindowAdapter());
+
+        //Display the window.
+        frame.pack();
+        frame.setSize(500, 500);
+        Util.showWindowWait(frame);
+        runRobotTest(frame);
+    }
+
+    private static void runRobotTest(Frame frame) {
+        try {
+            Thread robotThread = startRegTest(frame);
+            robotThread.start();
+            waitForThread(robotThread);
+        } finally {
+            frame.dispose();
+        }
+    }
+
+    private static void waitForThread(Thread t) {
+        while (t.isAlive()) {
+            try {
+                t.join();
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
+    private static void sleepFor(long millis) {
+        long dT = 0;
+        long start = System.nanoTime();
+        while (dT < millis) {
+            try {
+                long toSleep = millis - dT/1000000;
+                if (toSleep > 0) {
+                    Thread.sleep(toSleep);
+                }
+                // if this ends without an interrupted exception,
+                // that's good enough.
+                break;
+            } catch (InterruptedException e) {
+                long now = System.nanoTime();
+                dT = now - start;
+            }
+        }
+    }
+
+    private static void rmove(Robot robot, Point p) {
+        robot.mouseMove(p.x, p.y);
+    }
+    private static void rdown(Robot robot) {
+        robot.mousePress(InputEvent.BUTTON1_MASK);
+        robot.delay(50);
+    }
+    private static void rup(Robot robot) {
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        robot.delay(50);
+    }
+
+    public static void click(Robot robot) {
+        rdown(robot);
+        rup(robot);
+    }
+
+    public static void doubleClick(Robot robot) {
+        click(robot);
+        click(robot);
+    }
+
+    private static void dragWindow(Window w, int dx, int dy, Robot robot) {
+        Point p = Util.getTitlePoint(w);
+        rmove(robot, p);
+        rdown(robot);
+        p.translate(dx, dy);
+        rmove(robot, p);
+        rup(robot);
+    }
+
+    // f must be visible
+    private static Thread startRegTest(final Frame f) {
+        Thread robot = new Thread(new Runnable() {
+            public void run() {
+                Robot r = Util.createRobot();
+                dragWindow(f, 100, 100, r);
+                // wait for the location to be set.
+                sleepFor(2000);
+
+                final Point l2 = f.getLocationOnScreen();
+
+                // double click should maximize the frame
+                doubleClick(r);
+
+                // wait for location again.
+                sleepFor(2000);
+                final Point l3 = f.getLocationOnScreen();
+                if (l3.equals(l2)) {
+                    throw new RuntimeException("Bad location after maximize. Window location has not moved");
+                }
+            }
+        });
+        return robot;
+    }
+}
+
diff -r cf7c64f276c6 -r 49098163596b test/java/awt/regtesthelpers/Util.java
--- openjdk.orig/jdk/test/java/awt/regtesthelpers/Util.java	Wed May 11 11:08:03 2011 -0400
+++ openjdk/jdk/test/java/awt/regtesthelpers/Util.java	Tue May 17 10:35:27 2011 -0400
@@ -140,6 +140,13 @@
         robot.mouseMove(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
     }
 
+    public static Point getTitlePoint(Window decoratedWindow) {
+        Point p = decoratedWindow.getLocationOnScreen();
+        Dimension d = decoratedWindow.getSize();
+        return new Point(p.x + (int)(d.getWidth()/2),
+                         p.y + (int)decoratedWindow.getInsets().top/2);
+    }
+
     /**
      * Moves mouse pointer in the center of a given {@code comp} component
      * and performs a left mouse button click using the {@code robot} parameter
@@ -167,11 +174,9 @@
      * WARNING: it may fail on some platforms when the window is not wide enough.
      */
     public static void clickOnTitle(final Window decoratedWindow, final Robot robot) {
-        Point p = decoratedWindow.getLocationOnScreen();
-        Dimension d = decoratedWindow.getSize();
-
         if (decoratedWindow instanceof Frame || decoratedWindow instanceof Dialog) {
-            robot.mouseMove(p.x + (int)(d.getWidth()/2), p.y + (int)decoratedWindow.getInsets().top/2);
+            Point p = getTitlePoint(decoratedWindow);
+            robot.mouseMove(p.x, p.y);
             robot.delay(50);
             robot.mousePress(InputEvent.BUTTON1_MASK);
             robot.delay(50);
@@ -409,7 +414,8 @@
         ICE_WM = 10,
         METACITY_WM = 11,
         COMPIZ_WM = 12,
-        LG3D_WM = 13;
+        LG3D_WM = 13,
+        MUTTER_WM = 14;
 
     /*
      * Returns -1 in case of not X Window or any problems.
exporting patch:
<fdopen>
