Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/native_NOTIOS/sun/awt/CMenuBar.m
38829 views
/*1* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#import <AppKit/AppKit.h>26#import <JavaNativeFoundation/JavaNativeFoundation.h>27#import <JavaRuntimeSupport/JavaRuntimeSupport.h>282930#import "CMenuBar.h"31#import "CMenu.h"32#import "ThreadUtilities.h"3334#import "sun_lwawt_macosx_CMenuBar.h"3536__attribute__((visibility("default")))37NSString *CMenuBarDidReuseItemNotification =38@"CMenuBarDidReuseItemNotification";3940static CMenuBar *sActiveMenuBar = nil;41static NSMenu *sDefaultHelpMenu = nil;42static BOOL sSetupHelpMenu = NO;4344@interface CMenuBar (CMenuBar_Private)45+ (void) addDefaultHelpMenu;46@end4748@implementation CMenuBar4950+ (void)clearMenuBarExcludingAppleMenu_OnAppKitThread:(BOOL) excludingAppleMenu {51AWT_ASSERT_APPKIT_THREAD;52// Remove all Java menus from the main bar.53NSMenu *theMainMenu = [NSApp mainMenu];54NSUInteger i, menuCount = [theMainMenu numberOfItems];5556for (i = menuCount; i > 1; i--) {57NSUInteger index = i-1;5859NSMenuItem *currItem = [theMainMenu itemAtIndex:index];60NSMenu *currMenu = [currItem submenu];6162if (excludingAppleMenu && ![currMenu isJavaMenu]) {63continue;64}65[currItem setSubmenu:nil];66[theMainMenu removeItemAtIndex:index];67}6869[CMenuBar addDefaultHelpMenu];70}7172+ (BOOL) isActiveMenuBar:(CMenuBar *)inMenuBar {73return (sActiveMenuBar == inMenuBar);74}7576- (id) initWithPeer:(jobject)peer {77AWT_ASSERT_APPKIT_THREAD;78self = [super initWithPeer: peer];79if (self) {80fMenuList = [[NSMutableArray alloc] init];81}82return self;83}8485-(void) dealloc {86[fMenuList release];87fMenuList = nil;8889[fHelpMenu release];90fHelpMenu = nil;9192[super dealloc];93}9495+ (void) activate:(CMenuBar *)menubar modallyDisabled:(BOOL)modallyDisabled {96AWT_ASSERT_APPKIT_THREAD;9798if (!menubar) {99[CMenuBar clearMenuBarExcludingAppleMenu_OnAppKitThread:YES];100return;101}102103@synchronized([CMenuBar class]) {104sActiveMenuBar = menubar;105}106107@synchronized(menubar) {108menubar->fModallyDisabled = modallyDisabled;109}110111NSUInteger i = 0, newMenuListSize = [menubar->fMenuList count];112113NSMenu *theMainMenu = [NSApp mainMenu];114NSUInteger menuIndex, menuCount = [theMainMenu numberOfItems];115116NSUInteger cmenuIndex = 0, cmenuCount = newMenuListSize;117NSMutableArray *removedMenuArray = [NSMutableArray array];118119for (menuIndex = 0; menuIndex < menuCount; menuIndex++) {120NSMenuItem *currItem = [theMainMenu itemAtIndex:menuIndex];121NSMenu *currMenu = [currItem submenu];122123if ([currMenu isJavaMenu]) {124// Ready to replace, find next candidate125CMenu *newMenu = nil;126if (cmenuIndex < cmenuCount) {127newMenu = (CMenu *)[menubar->fMenuList objectAtIndex:cmenuIndex];128if (newMenu == menubar->fHelpMenu) {129cmenuIndex++;130if (cmenuIndex < cmenuCount) {131newMenu = (CMenu *)[menubar->fMenuList objectAtIndex:cmenuIndex];132}133}134}135if (newMenu) {136NSMenu *menuToAdd = [newMenu menu];137if ([theMainMenu indexOfItemWithSubmenu:menuToAdd] == -1) {138[[NSNotificationCenter defaultCenter] postNotificationName:CMenuBarDidReuseItemNotification object:theMainMenu];139140[currItem setSubmenu:menuToAdd];141[currItem setTitle:[menuToAdd title]];142cmenuIndex++;143}144145BOOL newEnabledState = [newMenu isEnabled] && !menubar->fModallyDisabled;146[currItem setEnabled:newEnabledState];147} else {148[removedMenuArray addObject:[NSNumber numberWithInteger:menuIndex]];149}150}151}152153// Clean up extra items154NSUInteger removedIndex, removedCount = [removedMenuArray count];155for (removedIndex=removedCount; removedIndex > 0; removedIndex--) {156NSUInteger index = [[removedMenuArray objectAtIndex:(removedIndex-1)] integerValue];157NSMenuItem *currItem = [theMainMenu itemAtIndex:index];158[currItem setSubmenu:nil];159[theMainMenu removeItemAtIndex:index];160}161162i = cmenuIndex;163164// Add all of the menus in the menu list.165for (; i < newMenuListSize; i++) {166CMenu *newMenu = (CMenu *)[menubar->fMenuList objectAtIndex:i];167168if (newMenu != menubar->fHelpMenu) {169NSArray *args = [NSArray arrayWithObjects:newMenu, [NSNumber numberWithInt:-1], nil];170[menubar nativeAddMenuAtIndex_OnAppKitThread:args];171}172}173174// Add the help menu last.175if (menubar->fHelpMenu) {176NSArray *args = [NSArray arrayWithObjects:menubar->fHelpMenu, [NSNumber numberWithInt:-1], nil];177[menubar nativeAddMenuAtIndex_OnAppKitThread:args];178} else {179[CMenuBar addDefaultHelpMenu];180}181}182183-(void) deactivate {184AWT_ASSERT_APPKIT_THREAD;185186@synchronized([CMenuBar class]) {187sActiveMenuBar = nil;188}189190@synchronized(self) {191fModallyDisabled = NO;192}193}194195-(void) javaAddMenu: (CMenu *)theMenu {196@synchronized(self) {197[fMenuList addObject: theMenu];198}199200if (self == sActiveMenuBar) {201NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:-1], nil];202[ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES];203[args release];204}205}206207// This method is a special case for use by the screen menu bar.208// See ScreenMenuBar.java -- used to implement setVisible(boolean) by209// removing or adding the menu from the current menu bar's list.210-(void) javaAddMenu: (CMenu *)theMenu atIndex:(jint)index {211@synchronized(self) {212if (index == -1){213[fMenuList addObject:theMenu];214}else{215[fMenuList insertObject:theMenu atIndex:index];216}217}218219if (self == sActiveMenuBar) {220NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:index], nil];221[ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES];222[args release];223}224}225226- (NSInteger) javaIndexToNSMenuIndex_OnAppKitThread:(jint)javaIndex {227AWT_ASSERT_APPKIT_THREAD;228NSInteger returnValue = -1;229NSMenu *theMainMenu = [NSApp mainMenu];230231if (javaIndex == -1) {232if (fHelpMenu) {233returnValue = [theMainMenu indexOfItemWithSubmenu:[fHelpMenu menu]];234}235} else {236CMenu *requestedMenu = [fMenuList objectAtIndex:javaIndex];237238if (requestedMenu == fHelpMenu) {239returnValue = [theMainMenu indexOfItemWithSubmenu:[fHelpMenu menu]];240} else {241NSUInteger i, menuCount = [theMainMenu numberOfItems];242jint currJavaMenuIndex = 0;243for (i = 0; i < menuCount; i++) {244NSMenuItem *currItem = [theMainMenu itemAtIndex:i];245NSMenu *currMenu = [currItem submenu];246247if ([currMenu isJavaMenu]) {248if (javaIndex == currJavaMenuIndex) {249returnValue = i;250break;251}252253currJavaMenuIndex++;254}255}256}257}258259return returnValue;260}261262- (void) nativeAddMenuAtIndex_OnAppKitThread:(NSArray *)args {263AWT_ASSERT_APPKIT_THREAD;264CMenu *theNewMenu = (CMenu*)[args objectAtIndex:0];265jint index = [(NSNumber*)[args objectAtIndex:1] intValue];266NSApplication *theApp = [NSApplication sharedApplication];267NSMenu *theMainMenu = [theApp mainMenu];268NSMenu *menuToAdd = [theNewMenu menu];269270if ([theMainMenu indexOfItemWithSubmenu:menuToAdd] == -1) {271NSMenuItem *newItem = [[NSMenuItem alloc] init];272[newItem setSubmenu:[theNewMenu menu]];273[newItem setTitle:[[theNewMenu menu] title]];274275NSInteger nsMenuIndex = [self javaIndexToNSMenuIndex_OnAppKitThread:index];276277if (nsMenuIndex == -1) {278[theMainMenu addItem:newItem];279} else {280[theMainMenu insertItem:newItem atIndex:nsMenuIndex];281}282283BOOL newEnabledState = [theNewMenu isEnabled] && !fModallyDisabled;284[newItem setEnabled:newEnabledState];285[newItem release];286}287}288289- (void) javaDeleteMenu: (jint)index {290if (self == sActiveMenuBar) {291[ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES];292}293294@synchronized(self) {295CMenu *menuToRemove = [fMenuList objectAtIndex:index];296297if (menuToRemove == fHelpMenu) {298[fHelpMenu release];299fHelpMenu = nil;300}301302[fMenuList removeObjectAtIndex:index];303}304}305306- (void) nativeDeleteMenu_OnAppKitThread:(id)indexObj {307AWT_ASSERT_APPKIT_THREAD;308NSApplication *theApp = [NSApplication sharedApplication];309NSMenu *theMainMenu = [theApp mainMenu];310jint menuToRemove = [(NSNumber *)indexObj intValue];311NSInteger nsMenuToRemove = [self javaIndexToNSMenuIndex_OnAppKitThread:menuToRemove];312313if (nsMenuToRemove != -1) {314[theMainMenu removeItemAtIndex:nsMenuToRemove];315}316}317318- (void) javaSetHelpMenu:(CMenu *)theMenu {319@synchronized(self) {320[theMenu retain];321[fHelpMenu release];322fHelpMenu = theMenu;323}324}325326+ (void) addDefaultHelpMenu {327AWT_ASSERT_APPKIT_THREAD;328329// Look for a help book tag. If it's there, add the help menu.330@synchronized ([CMenuBar class]) {331if (!sSetupHelpMenu) {332if (sDefaultHelpMenu == nil) {333// If we are embedded, don't make a help menu.334// TODO(cpc): we don't have NSApplicationAWT yet...335//if (![NSApp isKindOfClass:[NSApplicationAWT class]]) {336// sSetupHelpMenu = YES;337// return;338//}339340// If the developer specified a NIB, don't make a help menu.341// TODO(cpc): usingDefaultNib only defined on NSApplicationAWT342//if (![NSApp usingDefaultNib]) {343// sSetupHelpMenu = YES;344// return;345//}346347// TODO: not implemented348}349350sSetupHelpMenu = YES;351}352}353354if (sDefaultHelpMenu) {355NSMenu *theMainMenu = [NSApp mainMenu];356357if ([theMainMenu indexOfItemWithSubmenu:sDefaultHelpMenu] == -1) {358// Since we're re-using this NSMenu, we need to clear its parent before359// adding it to a new menu item, or else AppKit will complain.360[sDefaultHelpMenu setSupermenu:nil];361362// Add the help menu to the main menu.363NSMenuItem *newItem = [[NSMenuItem alloc] init];364[newItem setSubmenu:sDefaultHelpMenu];365[newItem setTitle:[sDefaultHelpMenu title]];366[theMainMenu addItem:newItem];367368// Release it so the main menu owns it.369[newItem release];370}371}372}373374@end375376/*377* Class: sun_lwawt_macosx_CMenuBar378* Method: nativeCreateMenuBar379* Signature: ()J380*/381JNIEXPORT jlong JNICALL382Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar383(JNIEnv *env, jobject peer)384{385__block CMenuBar *aCMenuBar = nil;386JNF_COCOA_ENTER(env);387388jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);389390[ThreadUtilities performOnMainThreadWaiting:YES block:^(){391392aCMenuBar = [[CMenuBar alloc] initWithPeer:cPeerObjGlobal];393// the aCMenuBar is released in CMenuComponent.dispose()394}];395if (aCMenuBar == nil) {396return 0L;397}398399JNF_COCOA_EXIT(env);400return ptr_to_jlong(aCMenuBar);401}402403/*404* Class: sun_lwawt_macosx_CMenuBar405* Method: nativeAddAtIndex406* Signature: (JJI)V407*/408JNIEXPORT void JNICALL409Java_sun_lwawt_macosx_CMenuBar_nativeAddAtIndex410(JNIEnv *env, jobject peer,411jlong menuBarObject, jlong menuObject, jint index)412{413JNF_COCOA_ENTER(env);414// Remove the specified item.415[((CMenuBar *) jlong_to_ptr(menuBarObject)) javaAddMenu:(CMenu *) jlong_to_ptr(menuObject) atIndex:index];416JNF_COCOA_EXIT(env);417}418419/*420* Class: sun_lwawt_macosx_CMenuBar421* Method: nativeDelMenu422* Signature: (JI)V423*/424JNIEXPORT void JNICALL425Java_sun_lwawt_macosx_CMenuBar_nativeDelMenu426(JNIEnv *env, jobject peer, jlong menuBarObject, jint index)427{428JNF_COCOA_ENTER(env);429// Remove the specified item.430[((CMenuBar *) jlong_to_ptr(menuBarObject)) javaDeleteMenu: index];431JNF_COCOA_EXIT(env);432}433434/*435* Class: sun_lwawt_macosx_CMenuBar436* Method: nativeSetHelpMenu437* Signature: (JJ)V438*/439JNIEXPORT void JNICALL440Java_sun_lwawt_macosx_CMenuBar_nativeSetHelpMenu441(JNIEnv *env, jobject peer, jlong menuBarObject, jlong menuObject)442{443JNF_COCOA_ENTER(env);444// Remove the specified item.445[((CMenuBar *) jlong_to_ptr(menuBarObject)) javaSetHelpMenu: ((CMenu *)jlong_to_ptr(menuObject))];446JNF_COCOA_EXIT(env);447}448449450