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