--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/sun/awt/CMenuBar.m Sun Aug 17 15:54:13 2014 +0100
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#import <AppKit/AppKit.h>
+#import <JavaNativeFoundation/JavaNativeFoundation.h>
+#import <JavaRuntimeSupport/JavaRuntimeSupport.h>
+
+
+#import "CMenuBar.h"
+#import "CMenu.h"
+#import "ThreadUtilities.h"
+
+#import "sun_lwawt_macosx_CMenuBar.h"
+
+__attribute__((visibility("default")))
+NSString *CMenuBarDidReuseItemNotification =
+ @"CMenuBarDidReuseItemNotification";
+
+static CMenuBar *sActiveMenuBar = nil;
+static NSMenu *sDefaultHelpMenu = nil;
+static BOOL sSetupHelpMenu = NO;
+
+@interface CMenuBar (CMenuBar_Private)
++ (void) addDefaultHelpMenu;
+@end
+
+@implementation CMenuBar
+
++ (void)clearMenuBarExcludingAppleMenu_OnAppKitThread:(BOOL) excludingAppleMenu {
+ AWT_ASSERT_APPKIT_THREAD;
+ // Remove all Java menus from the main bar.
+ NSMenu *theMainMenu = [NSApp mainMenu];
+ NSUInteger i, menuCount = [theMainMenu numberOfItems];
+
+ for (i = menuCount; i > 1; i--) {
+ NSUInteger index = i-1;
+
+ NSMenuItem *currItem = [theMainMenu itemAtIndex:index];
+ NSMenu *currMenu = [currItem submenu];
+
+ if (excludingAppleMenu && ![currMenu isJavaMenu]) {
+ continue;
+ }
+ [currItem setSubmenu:nil];
+ [theMainMenu removeItemAtIndex:index];
+ }
+
+ [CMenuBar addDefaultHelpMenu];
+}
+
++ (BOOL) isActiveMenuBar:(CMenuBar *)inMenuBar {
+ return (sActiveMenuBar == inMenuBar);
+}
+
+- (id) initWithPeer:(jobject)peer {
+ AWT_ASSERT_APPKIT_THREAD;
+ self = [super initWithPeer: peer];
+ if (self) {
+ fMenuList = [[NSMutableArray alloc] init];
+ }
+ return self;
+}
+
+-(void) dealloc {
+ [fMenuList release];
+ fMenuList = nil;
+
+ [fHelpMenu release];
+ fHelpMenu = nil;
+
+ [super dealloc];
+}
+
++ (void) activate:(CMenuBar *)menubar modallyDisabled:(BOOL)modallyDisabled {
+ AWT_ASSERT_APPKIT_THREAD;
+
+ if (!menubar) {
+ [CMenuBar clearMenuBarExcludingAppleMenu_OnAppKitThread:YES];
+ return;
+ }
+
+ @synchronized([CMenuBar class]) {
+ sActiveMenuBar = menubar;
+ }
+
+ @synchronized(menubar) {
+ menubar->fModallyDisabled = modallyDisabled;
+ }
+
+ NSUInteger i = 0, newMenuListSize = [menubar->fMenuList count];
+
+ NSMenu *theMainMenu = [NSApp mainMenu];
+ NSUInteger menuIndex, menuCount = [theMainMenu numberOfItems];
+
+ NSUInteger cmenuIndex = 0, cmenuCount = newMenuListSize;
+ NSMutableArray *removedMenuArray = [NSMutableArray array];
+
+ for (menuIndex = 0; menuIndex < menuCount; menuIndex++) {
+ NSMenuItem *currItem = [theMainMenu itemAtIndex:menuIndex];
+ NSMenu *currMenu = [currItem submenu];
+
+ if ([currMenu isJavaMenu]) {
+ // Ready to replace, find next candidate
+ CMenu *newMenu = nil;
+ if (cmenuIndex < cmenuCount) {
+ newMenu = (CMenu *)[menubar->fMenuList objectAtIndex:cmenuIndex];
+ if (newMenu == menubar->fHelpMenu) {
+ cmenuIndex++;
+ if (cmenuIndex < cmenuCount) {
+ newMenu = (CMenu *)[menubar->fMenuList objectAtIndex:cmenuIndex];
+ }
+ }
+ }
+ if (newMenu) {
+ NSMenu *menuToAdd = [newMenu menu];
+ if ([theMainMenu indexOfItemWithSubmenu:menuToAdd] == -1) {
+ [[NSNotificationCenter defaultCenter] postNotificationName:CMenuBarDidReuseItemNotification object:theMainMenu];
+
+ [currItem setSubmenu:menuToAdd];
+ [currItem setTitle:[menuToAdd title]];
+ cmenuIndex++;
+ }
+
+ BOOL newEnabledState = [newMenu isEnabled] && !menubar->fModallyDisabled;
+ [currItem setEnabled:newEnabledState];
+ } else {
+ [removedMenuArray addObject:[NSNumber numberWithInteger:menuIndex]];
+ }
+ }
+ }
+
+ // Clean up extra items
+ NSUInteger removedIndex, removedCount = [removedMenuArray count];
+ for (removedIndex=removedCount; removedIndex > 0; removedIndex--) {
+ NSUInteger index = [[removedMenuArray objectAtIndex:(removedIndex-1)] integerValue];
+ NSMenuItem *currItem = [theMainMenu itemAtIndex:index];
+ [currItem setSubmenu:nil];
+ [theMainMenu removeItemAtIndex:index];
+ }
+
+ i = cmenuIndex;
+
+ // Add all of the menus in the menu list.
+ for (; i < newMenuListSize; i++) {
+ CMenu *newMenu = (CMenu *)[menubar->fMenuList objectAtIndex:i];
+
+ if (newMenu != menubar->fHelpMenu) {
+ NSArray *args = [NSArray arrayWithObjects:newMenu, [NSNumber numberWithInt:-1], nil];
+ [menubar nativeAddMenuAtIndex_OnAppKitThread:args];
+ }
+ }
+
+ // Add the help menu last.
+ if (menubar->fHelpMenu) {
+ NSArray *args = [NSArray arrayWithObjects:menubar->fHelpMenu, [NSNumber numberWithInt:-1], nil];
+ [menubar nativeAddMenuAtIndex_OnAppKitThread:args];
+ } else {
+ [CMenuBar addDefaultHelpMenu];
+ }
+}
+
+-(void) deactivate {
+ AWT_ASSERT_APPKIT_THREAD;
+
+ @synchronized([CMenuBar class]) {
+ sActiveMenuBar = nil;
+ }
+
+ @synchronized(self) {
+ fModallyDisabled = NO;
+ }
+}
+
+-(void) javaAddMenu: (CMenu *)theMenu {
+ @synchronized(self) {
+ [fMenuList addObject: theMenu];
+ }
+
+ if (self == sActiveMenuBar) {
+ NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:-1], nil];
+ [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES];
+ [args release];
+ }
+}
+
+// This method is a special case for use by the screen menu bar.
+// See ScreenMenuBar.java -- used to implement setVisible(boolean) by
+// removing or adding the menu from the current menu bar's list.
+-(void) javaAddMenu: (CMenu *)theMenu atIndex:(jint)index {
+ @synchronized(self) {
+ if (index == -1){
+ [fMenuList addObject:theMenu];
+ }else{
+ [fMenuList insertObject:theMenu atIndex:index];
+ }
+ }
+
+ if (self == sActiveMenuBar) {
+ NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:index], nil];
+ [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES];
+ [args release];
+ }
+}
+
+- (NSInteger) javaIndexToNSMenuIndex_OnAppKitThread:(jint)javaIndex {
+ AWT_ASSERT_APPKIT_THREAD;
+ NSInteger returnValue = -1;
+ NSMenu *theMainMenu = [NSApp mainMenu];
+
+ if (javaIndex == -1) {
+ if (fHelpMenu) {
+ returnValue = [theMainMenu indexOfItemWithSubmenu:[fHelpMenu menu]];
+ }
+ } else {
+ CMenu *requestedMenu = [fMenuList objectAtIndex:javaIndex];
+
+ if (requestedMenu == fHelpMenu) {
+ returnValue = [theMainMenu indexOfItemWithSubmenu:[fHelpMenu menu]];
+ } else {
+ NSUInteger i, menuCount = [theMainMenu numberOfItems];
+ jint currJavaMenuIndex = 0;
+ for (i = 0; i < menuCount; i++) {
+ NSMenuItem *currItem = [theMainMenu itemAtIndex:i];
+ NSMenu *currMenu = [currItem submenu];
+
+ if ([currMenu isJavaMenu]) {
+ if (javaIndex == currJavaMenuIndex) {
+ returnValue = i;
+ break;
+ }
+
+ currJavaMenuIndex++;
+ }
+ }
+ }
+ }
+
+ return returnValue;
+}
+
+- (void) nativeAddMenuAtIndex_OnAppKitThread:(NSArray *)args {
+ AWT_ASSERT_APPKIT_THREAD;
+ CMenu *theNewMenu = (CMenu*)[args objectAtIndex:0];
+ jint index = [(NSNumber*)[args objectAtIndex:1] intValue];
+ NSApplication *theApp = [NSApplication sharedApplication];
+ NSMenu *theMainMenu = [theApp mainMenu];
+ NSMenu *menuToAdd = [theNewMenu menu];
+
+ if ([theMainMenu indexOfItemWithSubmenu:menuToAdd] == -1) {
+ NSMenuItem *newItem = [[NSMenuItem alloc] init];
+ [newItem setSubmenu:[theNewMenu menu]];
+ [newItem setTitle:[[theNewMenu menu] title]];
+
+ NSInteger nsMenuIndex = [self javaIndexToNSMenuIndex_OnAppKitThread:index];
+
+ if (nsMenuIndex == -1) {
+ [theMainMenu addItem:newItem];
+ } else {
+ [theMainMenu insertItem:newItem atIndex:nsMenuIndex];
+ }
+
+ BOOL newEnabledState = [theNewMenu isEnabled] && !fModallyDisabled;
+ [newItem setEnabled:newEnabledState];
+ [newItem release];
+ }
+}
+
+- (void) javaDeleteMenu: (jint)index {
+ if (self == sActiveMenuBar) {
+ [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES];
+ }
+
+ @synchronized(self) {
+ CMenu *menuToRemove = [fMenuList objectAtIndex:index];
+
+ if (menuToRemove == fHelpMenu) {
+ [fHelpMenu release];
+ fHelpMenu = nil;
+ }
+
+ [fMenuList removeObjectAtIndex:index];
+ }
+}
+
+- (void) nativeDeleteMenu_OnAppKitThread:(id)indexObj {
+ AWT_ASSERT_APPKIT_THREAD;
+ NSApplication *theApp = [NSApplication sharedApplication];
+ NSMenu *theMainMenu = [theApp mainMenu];
+ jint menuToRemove = [(NSNumber *)indexObj intValue];
+ NSInteger nsMenuToRemove = [self javaIndexToNSMenuIndex_OnAppKitThread:menuToRemove];
+
+ if (nsMenuToRemove != -1) {
+ [theMainMenu removeItemAtIndex:nsMenuToRemove];
+ }
+}
+
+- (void) javaSetHelpMenu:(CMenu *)theMenu {
+ @synchronized(self) {
+ [theMenu retain];
+ [fHelpMenu release];
+ fHelpMenu = theMenu;
+ }
+}
+
++ (void) addDefaultHelpMenu {
+ AWT_ASSERT_APPKIT_THREAD;
+
+ // Look for a help book tag. If it's there, add the help menu.
+ @synchronized ([CMenuBar class]) {
+ if (!sSetupHelpMenu) {
+ if (sDefaultHelpMenu == nil) {
+ // If we are embedded, don't make a help menu.
+ // TODO(cpc): we don't have NSApplicationAWT yet...
+ //if (![NSApp isKindOfClass:[NSApplicationAWT class]]) {
+ // sSetupHelpMenu = YES;
+ // return;
+ //}
+
+ // If the developer specified a NIB, don't make a help menu.
+ // TODO(cpc): usingDefaultNib only defined on NSApplicationAWT
+ //if (![NSApp usingDefaultNib]) {
+ // sSetupHelpMenu = YES;
+ // return;
+ //}
+
+ // TODO: not implemented
+ }
+
+ sSetupHelpMenu = YES;
+ }
+ }
+
+ if (sDefaultHelpMenu) {
+ NSMenu *theMainMenu = [NSApp mainMenu];
+
+ if ([theMainMenu indexOfItemWithSubmenu:sDefaultHelpMenu] == -1) {
+ // Since we're re-using this NSMenu, we need to clear its parent before
+ // adding it to a new menu item, or else AppKit will complain.
+ [sDefaultHelpMenu setSupermenu:nil];
+
+ // Add the help menu to the main menu.
+ NSMenuItem *newItem = [[NSMenuItem alloc] init];
+ [newItem setSubmenu:sDefaultHelpMenu];
+ [newItem setTitle:[sDefaultHelpMenu title]];
+ [theMainMenu addItem:newItem];
+
+ // Release it so the main menu owns it.
+ [newItem release];
+ }
+ }
+}
+
+@end
+
+/*
+ * Class: sun_lwawt_macosx_CMenuBar
+ * Method: nativeCreateMenuBar
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar
+ (JNIEnv *env, jobject peer)
+{
+ CMenuBar *aCMenuBar = nil;
+ JNF_COCOA_ENTER(env);
+
+ jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
+
+ // We use an array here only to be able to get a return value
+ NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
+
+ [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES];
+
+ aCMenuBar = (CMenuBar *)[args objectAtIndex: 0];
+
+ if (aCMenuBar == nil) {
+ return 0L;
+ }
+
+ // [args release];
+
+ // A strange memory managment after that.
+
+
+ JNF_COCOA_EXIT(env);
+ return ptr_to_jlong(aCMenuBar);
+}
+
+/*
+ * Class: sun_lwawt_macosx_CMenuBar
+ * Method: nativeAddAtIndex
+ * Signature: (JJI)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_lwawt_macosx_CMenuBar_nativeAddAtIndex
+ (JNIEnv *env, jobject peer,
+ jlong menuBarObject, jlong menuObject, jint index)
+{
+ JNF_COCOA_ENTER(env);
+ // Remove the specified item.
+ [((CMenuBar *) jlong_to_ptr(menuBarObject)) javaAddMenu:(CMenu *) jlong_to_ptr(menuObject) atIndex:index];
+ JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class: sun_lwawt_macosx_CMenuBar
+ * Method: nativeDelMenu
+ * Signature: (JI)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_lwawt_macosx_CMenuBar_nativeDelMenu
+ (JNIEnv *env, jobject peer, jlong menuBarObject, jint index)
+{
+ JNF_COCOA_ENTER(env);
+ // Remove the specified item.
+ [((CMenuBar *) jlong_to_ptr(menuBarObject)) javaDeleteMenu: index];
+ JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class: sun_lwawt_macosx_CMenuBar
+ * Method: nativeSetHelpMenu
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_lwawt_macosx_CMenuBar_nativeSetHelpMenu
+ (JNIEnv *env, jobject peer, jlong menuBarObject, jlong menuObject)
+{
+ JNF_COCOA_ENTER(env);
+ // Remove the specified item.
+ [((CMenuBar *) jlong_to_ptr(menuBarObject)) javaSetHelpMenu: ((CMenu *)jlong_to_ptr(menuObject))];
+ JNF_COCOA_EXIT(env);
+}