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