--- old/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2018-08-30 19:15:33.000000000 +0530 +++ new/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2018-08-30 19:15:32.000000000 +0530 @@ -1205,17 +1205,27 @@ } private void orderAboveSiblings() { - // Recursively pop up the windows from the very bottom, (i.e. root owner) so that - // the windows are ordered above their nearest owner; ancestors of the window, - // which is going to become 'main window', are placed above their siblings. CPlatformWindow rootOwner = getRootOwner(); - if (rootOwner.isVisible() && !rootOwner.isIconified()) { - rootOwner.execute(CWrapper.NSWindow::orderFront); - } + // Do not order child windows of iconified owner. if (!rootOwner.isIconified()) { final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor(); - orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target)); + Window[] windows = windowAccessor.getOwnedWindows(rootOwner.target); + + // No need to order windows if it doesn't own other windows and hence return + if (windows.length == 0) { + return; + } + + // Recursively pop up the windows from the very bottom, (i.e. root owner) so that + // the windows are ordered above their nearest owner; ancestors of the window, + // which is going to become 'main window', are placed above their siblings. + if (rootOwner.isVisible()) { + rootOwner.execute(CWrapper.NSWindow::orderFront); + } + + // Order child windows. + orderAboveSiblingsImpl(windows); } } --- /dev/null 2018-08-30 19:15:34.000000000 +0530 +++ new/test/jdk/java/awt/Frame/CycleThroughFrameTest/CycleThroughFrameTest.java 2018-08-30 19:15:34.000000000 +0530 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2018, 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 + @key headful + @bug 8206392 + @requires (os.family == "mac") + @summary Cycle through frames using keyboard shortcut doesn't work on Mac + @compile CycleThroughFrameTest.java + @run main/manual CycleThroughFrameTest +*/ + +import java.awt.Frame; +import java.awt.Button; +import java.awt.TextArea; +import java.awt.FlowLayout; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class CycleThroughFrameTest { + + public static final int maxFrames = 5; + private static JFrame[] frame; + private static Frame instructionFrame; + private static volatile boolean testContinueFlag = true; + + private static final String TEST_INSTRUCTIONS = + " This is a manual test\n\n" + + " 1) Configure Keyboard shortcut if not done in your system:\n" + + " 2) Open System Preferences, go to -> Keyboard -> Shortcuts -> Keyboard\n" + + " 3) Enable 'Move focus to next window' if disabled\n" + + " 4) Enable 'Move focus to next window drawer' if disabled\n" + + " 5) Close System Preferences\n" + + " 5) Press COMMAND + ` keys to cycle through frames in forward order\n" + + " 6) Press FAIL if focus doesn't move to next frame\n" + + " 7) Press COMMAND + SHIFT + ` to cycle through frames in reverse order\n" + + " 8) Press FAIL if focus doesn't move to next frame in reverse order\n" + + " 9) Press PASS otherwise"; + + private static final String FAIL_MESSAGE = "Focus doesn't move to next frame"; + + public void showJFrame(int frameNumber) { + + String title = "Frame " + frameNumber; + frame[frameNumber] = new JFrame(title); + frame[frameNumber].setSize(300, 200); + frame[frameNumber].setLocation(50+(frameNumber*20), 50+(frameNumber*20)); + frame[frameNumber].setVisible(true); + } + + private void createAndShowFrame() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame = new JFrame[maxFrames]; + for (int i = 0; i < maxFrames; i++) { + showJFrame(i); + } + } + }); + } + + public void createAndShowInstructionFrame() { + Button passButton = new Button("Pass"); + passButton.setEnabled(true); + + Button failButton = new Button("Fail"); + failButton.setEnabled(true); + + TextArea instructions = new TextArea(12, 70); + instructions.setText(TEST_INSTRUCTIONS); + + instructionFrame = new Frame("Test Instructions"); + instructionFrame.add(passButton); + instructionFrame.add(failButton); + instructionFrame.add(instructions); + instructionFrame.setSize(200,200); + instructionFrame.setLayout(new FlowLayout()); + instructionFrame.pack(); + instructionFrame.setVisible(true); + + passButton.addActionListener(ae -> { + dispose(); + testContinueFlag = false; + }); + + failButton.addActionListener(ae -> { + dispose(); + testContinueFlag = false; + throw new RuntimeException(FAIL_MESSAGE); + }); + } + + private static void dispose() { + for (int i = 0; i < maxFrames; i++) { + frame[i].dispose(); + } + instructionFrame.dispose(); + } + + public static void main(String[] args) throws Exception { + + CycleThroughFrameTest testObj = new CycleThroughFrameTest(); + testObj.createAndShowFrame(); + testObj.createAndShowInstructionFrame(); + + final int sleepTime = 300000; + final int sleepLoopTime = 1000; + int remainingSleepTime = sleepTime; + while(remainingSleepTime > 0 && testContinueFlag) { + Thread.sleep(sleepLoopTime); + remainingSleepTime -= sleepLoopTime; + } + + if (testContinueFlag) { + dispose(); + throw new RuntimeException("Timed out after " + + (sleepTime - remainingSleepTime) / 1000 + " seconds"); + } + } +} +