1 /* 2 * Copyright (c) 2011, 2016, 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 package com.apple.eawt; 27 28 import java.awt.Container; 29 import java.awt.Frame; 30 31 32 import javax.swing.JFrame; 33 import javax.swing.JLayeredPane; 34 import javax.swing.JMenuBar; 35 import javax.swing.plaf.MenuBarUI; 36 37 import com.apple.laf.ScreenMenuBar; 38 import sun.awt.AWTAccessor; 39 import sun.lwawt.macosx.CMenuBar; 40 41 import com.apple.laf.AquaMenuBarUI; 42 43 class _AppMenuBarHandler { 44 private static final int MENU_ABOUT = 1; 45 private static final int MENU_PREFS = 2; 46 47 private static native void nativeSetMenuState(final int menu, final boolean visible, final boolean enabled); 48 private static native void nativeSetDefaultMenuBar(final long menuBarPeer); 49 50 static final _AppMenuBarHandler instance = new _AppMenuBarHandler(); 51 static _AppMenuBarHandler getInstance() { 52 return instance; 53 } 54 55 // callback from the native delegate -init function 56 private static void initMenuStates(final boolean aboutMenuItemVisible, 57 final boolean aboutMenuItemEnabled, 58 final boolean prefsMenuItemVisible, 59 final boolean prefsMenuItemEnabled) { 60 synchronized (instance) { 61 instance.aboutMenuItemVisible = aboutMenuItemVisible; 62 instance.aboutMenuItemEnabled = aboutMenuItemEnabled; 63 instance.prefsMenuItemVisible = prefsMenuItemVisible; 64 instance.prefsMenuItemEnabled = prefsMenuItemEnabled; 65 } 66 } 67 68 _AppMenuBarHandler() { } 69 70 boolean aboutMenuItemVisible; 71 boolean aboutMenuItemEnabled; 72 73 boolean prefsMenuItemVisible; 74 boolean prefsMenuItemEnabled; 75 boolean prefsMenuItemExplicitlySet; 76 77 void setDefaultMenuBar(final JMenuBar menuBar) { 78 installDefaultMenuBar(menuBar); 79 80 // scan the current frames, and see if any are foreground 81 final Frame[] frames = Frame.getFrames(); 82 for (final Frame frame : frames) { 83 if (frame.isVisible() && !isFrameMinimized(frame)) { 84 return; 85 } 86 } 87 88 // if we have no foreground frames, then we have to "kick" the menubar 89 final JFrame pingFrame = new JFrame(); 90 pingFrame.getRootPane().putClientProperty("Window.alpha", Float.valueOf(0.0f)); 91 pingFrame.setUndecorated(true); 92 pingFrame.setVisible(true); 93 pingFrame.toFront(); 94 pingFrame.setVisible(false); 95 pingFrame.dispose(); 96 } 97 98 static boolean isFrameMinimized(final Frame frame) { 99 return (frame.getExtendedState() & Frame.ICONIFIED) != 0; 100 } 101 102 static void installDefaultMenuBar(final JMenuBar menuBar) { 103 if (menuBar == null) { 104 // intentionally clearing the default menu 105 nativeSetDefaultMenuBar(0); 106 return; 107 } 108 109 Container parent = menuBar.getParent(); 110 if (parent instanceof JLayeredPane) { 111 ((JLayeredPane) parent).remove(menuBar); 112 } 113 114 MenuBarUI ui = menuBar.getUI(); 115 if (!(ui instanceof AquaMenuBarUI)) { 116 ui = new AquaMenuBarUI(); 117 menuBar.setUI(ui); 118 } 119 120 final AquaMenuBarUI aquaUI = (AquaMenuBarUI)ui; 121 final ScreenMenuBar screenMenuBar = aquaUI.getScreenMenuBar(); 122 if (screenMenuBar == null) { 123 // Aqua is installed, but we aren't using the screen menu bar 124 throw new IllegalStateException("Application.setDefaultMenuBar() only works if apple.laf.useScreenMenuBar=true"); 125 } 126 127 screenMenuBar.addNotify(); 128 final Object peer = AWTAccessor.getMenuComponentAccessor().getPeer(screenMenuBar); 129 if (!(peer instanceof CMenuBar)) { 130 // such a thing should not be possible 131 throw new IllegalStateException("Unable to determine native menu bar from provided JMenuBar"); 132 } 133 134 // grab the pointer to the CMenuBar, and retain it in native 135 ((CMenuBar) peer).execute(_AppMenuBarHandler::nativeSetDefaultMenuBar); 136 } 137 138 void setAboutMenuItemVisible(final boolean present) { 139 synchronized (this) { 140 if (aboutMenuItemVisible == present) return; 141 aboutMenuItemVisible = present; 142 } 143 144 nativeSetMenuState(MENU_ABOUT, aboutMenuItemVisible, aboutMenuItemEnabled); 145 } 146 147 void setPreferencesMenuItemVisible(final boolean present) { 148 synchronized (this) { 149 prefsMenuItemExplicitlySet = true; 150 if (prefsMenuItemVisible == present) return; 151 prefsMenuItemVisible = present; 152 } 153 nativeSetMenuState(MENU_PREFS, prefsMenuItemVisible, prefsMenuItemEnabled); 154 } 155 156 void setAboutMenuItemEnabled(final boolean enable) { 157 synchronized (this) { 158 if (aboutMenuItemEnabled == enable) return; 159 aboutMenuItemEnabled = enable; 160 } 161 nativeSetMenuState(MENU_ABOUT, aboutMenuItemVisible, aboutMenuItemEnabled); 162 } 163 164 void setPreferencesMenuItemEnabled(final boolean enable) { 165 synchronized (this) { 166 prefsMenuItemExplicitlySet = true; 167 if (prefsMenuItemEnabled == enable) return; 168 prefsMenuItemEnabled = enable; 169 } 170 nativeSetMenuState(MENU_PREFS, prefsMenuItemVisible, prefsMenuItemEnabled); 171 } 172 173 boolean isAboutMenuItemVisible() { 174 return aboutMenuItemVisible; 175 } 176 177 boolean isPreferencesMenuItemVisible() { 178 return prefsMenuItemVisible; 179 } 180 181 boolean isAboutMenuItemEnabled() { 182 return aboutMenuItemEnabled; 183 } 184 185 boolean isPreferencesMenuItemEnabled() { 186 return prefsMenuItemEnabled; 187 } 188 }