1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /** 27 * @test 28 * @key headful 29 * @bug 8146310 30 * @summary [macosx] setDefaultMenuBar does not initialize screen menu bar 31 * @author Alan Snyder 32 * @run main/othervm TestNoScreenMenuBar 33 * @requires (os.family == "mac") 34 */ 35 36 import java.awt.AWTException; 37 import java.awt.Desktop; 38 import java.awt.Robot; 39 import java.awt.event.InputEvent; 40 import java.io.IOException; 41 import java.lang.reflect.InvocationTargetException; 42 import javax.swing.JMenu; 43 import javax.swing.JMenuBar; 44 import javax.swing.JMenuItem; 45 import javax.swing.SwingUtilities; 46 47 public class TestNoScreenMenuBar 48 { 49 static TestNoScreenMenuBar theTest; 50 private Robot robot; 51 private boolean isApplicationOpened; 52 private boolean isActionPerformed; 53 54 public TestNoScreenMenuBar(String[] args) 55 { 56 try { 57 robot = new Robot(); 58 robot.setAutoDelay(50); 59 } catch (AWTException ex) { 60 throw new RuntimeException(ex); 61 } 62 63 if (!(args.length > 0 && args[0].equals("baseline"))) { 64 // activate another application 65 openOtherApplication(); 66 robot.delay(500); 67 } 68 69 // The failure mode is installing the default menu bar while the application is inactive 70 Desktop desktop = Desktop.getDesktop(); 71 desktop.setDefaultMenuBar(createMenuBar()); 72 73 robot.delay(500); 74 desktop.requestForeground(true); 75 robot.delay(500); 76 } 77 78 JMenuBar createMenuBar() 79 { 80 JMenuBar mb = new JMenuBar(); 81 // A very long name makes it more likely that the robot will hit the menu 82 JMenu menu = new JMenu("TestTestTestTestTestTestTestTestTestTest"); 83 mb.add(menu); 84 JMenuItem item = new JMenuItem("TestTestTestTestTestTestTestTestTestTest"); 85 item.addActionListener(ev -> { 86 isActionPerformed = true; 87 }); 88 menu.add(item); 89 return mb; 90 } 91 92 void dispose() 93 { 94 closeOtherApplication(); 95 Desktop.getDesktop().setDefaultMenuBar(null); 96 } 97 98 private void performMenuItemTest() 99 { 100 // Find the menu on the screen menu bar 101 // The location depends upon the application name which is the name of the first menu. 102 // Unfortunately, the application name can vary based on how the application is run. 103 // The work around is to make the menu and the menu item names very long. 104 105 int menuBarX = 250; 106 int menuBarY = 11; 107 int menuItemX = menuBarX; 108 int menuItemY = 34; 109 110 robot.mouseMove(menuBarX, menuBarY); 111 robot.delay(100); 112 robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); 113 robot.delay(100); 114 robot.mouseMove(menuItemX, menuItemY); 115 robot.delay(100); 116 robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); 117 robot.waitForIdle(); 118 119 waitForAction(); 120 } 121 122 private synchronized void waitForAction() 123 { 124 try { 125 for (int i = 0; i < 10; i++) { 126 if (isActionPerformed) { 127 return; 128 } 129 wait(100); 130 } 131 } catch (InterruptedException ex) { 132 } 133 throw new RuntimeException("Test failed: menu item action was not performed"); 134 } 135 136 private void openOtherApplication() { 137 String[] cmd = { "/usr/bin/open", "/Applications/System Preferences.app" }; 138 execute(cmd); 139 isApplicationOpened = true; 140 } 141 142 private void closeOtherApplication() { 143 if (isApplicationOpened) { 144 String[] cmd = { "/usr/bin/osascript", "-e", "tell application \"System Preferences\" to close window 1" }; 145 execute(cmd); 146 } 147 } 148 149 private void execute(String[] cmd) { 150 try { 151 Process p = Runtime.getRuntime().exec(cmd); 152 p.waitFor(); 153 } catch (IOException | InterruptedException ex) { 154 throw new RuntimeException("Unable to execute command"); 155 } 156 } 157 158 private static void runSwing(Runnable r) 159 { 160 try { 161 SwingUtilities.invokeAndWait(r); 162 } catch (InterruptedException e) { 163 } catch (InvocationTargetException e) { 164 throw new RuntimeException(e); 165 } 166 } 167 168 public static void main(String[] args) 169 { 170 if (!System.getProperty("os.name").contains("OS X")) { 171 System.out.println("This test is for MacOS only. Automatically passed on other platforms."); 172 return; 173 } 174 175 System.setProperty("apple.laf.useScreenMenuBar", "true"); 176 try { 177 runSwing(() -> theTest = new TestNoScreenMenuBar(args)); 178 theTest.performMenuItemTest(); 179 } finally { 180 if (theTest != null) { 181 runSwing(() -> theTest.dispose()); 182 } 183 } 184 } 185 }