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