annotate src/macosx/native/sun/awt/CMenu.m @ 7871:d502cc7bcc3d

8006634: Unify LWCToolkit.invokeAndWait() and sun.awt.datatransfer.ToolkitThreadBlockedHandler Summary: Changed the logic for the nested event loops and deleted deadlock detection Reviewed-by: art, denis
author pchelko
date Mon, 25 Feb 2013 10:17:25 +0000
parents 5309fed435b5
children
rev   line source
michaelm@5177 1 /*
michaelm@5177 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
michaelm@5177 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
michaelm@5177 4 *
michaelm@5177 5 * This code is free software; you can redistribute it and/or modify it
michaelm@5177 6 * under the terms of the GNU General Public License version 2 only, as
michaelm@5177 7 * published by the Free Software Foundation. Oracle designates this
michaelm@5177 8 * particular file as subject to the "Classpath" exception as provided
michaelm@5177 9 * by Oracle in the LICENSE file that accompanied this code.
michaelm@5177 10 *
michaelm@5177 11 * This code is distributed in the hope that it will be useful, but WITHOUT
michaelm@5177 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
michaelm@5177 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
michaelm@5177 14 * version 2 for more details (a copy is included in the LICENSE file that
michaelm@5177 15 * accompanied this code).
michaelm@5177 16 *
michaelm@5177 17 * You should have received a copy of the GNU General Public License version
michaelm@5177 18 * 2 along with this work; if not, write to the Free Software Foundation,
michaelm@5177 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
michaelm@5177 20 *
michaelm@5177 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
michaelm@5177 22 * or visit www.oracle.com if you need additional information or have any
michaelm@5177 23 * questions.
michaelm@5177 24 */
michaelm@5177 25
michaelm@5177 26 #import <JavaNativeFoundation/JavaNativeFoundation.h>
michaelm@5177 27 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
michaelm@5177 28
michaelm@5177 29
michaelm@5177 30 #import "CMenu.h"
michaelm@5177 31 #import "CMenuBar.h"
michaelm@5177 32 #import "ThreadUtilities.h"
michaelm@5177 33
michaelm@5177 34 #import "sun_lwawt_macosx_CMenu.h"
michaelm@5177 35
michaelm@5177 36 @implementation CMenu
michaelm@5177 37
michaelm@5177 38 - (id)initWithPeer:(jobject)peer {
michaelm@5177 39 AWT_ASSERT_APPKIT_THREAD;
michaelm@5177 40 // Create the new NSMenu
michaelm@5177 41 self = [super initWithPeer:peer asSeparator:[NSNumber numberWithBool:NO]];
michaelm@5177 42 if (self) {
michaelm@5177 43 fMenu = [NSMenu javaMenuWithTitle:@""];
michaelm@5177 44 [fMenu retain];
michaelm@5177 45 [fMenu setAutoenablesItems:NO];
michaelm@5177 46 }
michaelm@5177 47 return self;
michaelm@5177 48 }
michaelm@5177 49
michaelm@5177 50 - (void)dealloc {
michaelm@5177 51 [fMenu release];
michaelm@5177 52 fMenu = nil;
michaelm@5177 53 [super dealloc];
michaelm@5177 54 }
michaelm@5177 55 //- (void)finalize { [super finalize]; }
michaelm@5177 56
michaelm@5177 57 - (void)addJavaSubmenu:(CMenu *)submenu {
pchelko@7871 58 [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:submenu waitUntilDone:YES];
michaelm@5177 59 }
michaelm@5177 60
michaelm@5177 61 - (void)addJavaMenuItem:(CMenuItem *)theMenuItem {
pchelko@7871 62 [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:theMenuItem waitUntilDone:YES];
michaelm@5177 63 }
michaelm@5177 64
michaelm@5177 65 - (void)addNativeItem_OnAppKitThread:(CMenuItem *)itemModified {
michaelm@5177 66 AWT_ASSERT_APPKIT_THREAD;
michaelm@5177 67 [itemModified addNSMenuItemToMenu:[self menu]];
michaelm@5177 68 }
michaelm@5177 69
michaelm@5177 70 - (void)setJavaMenuTitle:(NSString *)title {
michaelm@5177 71
michaelm@5177 72 if (title) {
pchelko@7871 73 [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) on:self withObject:title waitUntilDone:YES];
michaelm@5177 74 }
michaelm@5177 75 }
michaelm@5177 76
michaelm@5177 77 - (void)setNativeMenuTitle_OnAppKitThread:(NSString *)title {
michaelm@5177 78 AWT_ASSERT_APPKIT_THREAD;
michaelm@5177 79
michaelm@5177 80 [fMenu setTitle:title];
michaelm@5177 81 // If we are a submenu we need to set our name in the parent menu's menu item.
michaelm@5177 82 NSMenu *parent = [fMenu supermenu];
michaelm@5177 83 if (parent) {
michaelm@5177 84 NSInteger index = [parent indexOfItemWithSubmenu:fMenu];
michaelm@5177 85 NSMenuItem *menuItem = [parent itemAtIndex:index];
michaelm@5177 86 [menuItem setTitle:title];
michaelm@5177 87 }
michaelm@5177 88 }
michaelm@5177 89
michaelm@5177 90 - (void)addSeparator {
michaelm@5177 91 // Nothing calls this, which is good because we need a CMenuItem here.
michaelm@5177 92 }
michaelm@5177 93
michaelm@5177 94 - (void)deleteJavaItem:(jint)index {
michaelm@5177 95
pchelko@7871 96 [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES];
michaelm@5177 97 }
michaelm@5177 98
michaelm@5177 99 - (void)deleteNativeJavaItem_OnAppKitThread:(NSNumber *)number {
michaelm@5177 100 AWT_ASSERT_APPKIT_THREAD;
michaelm@5177 101
michaelm@5177 102 int n = [number intValue];
michaelm@5177 103 if (n < [[self menu] numberOfItems]) {
michaelm@5177 104 [[self menu] removeItemAtIndex:n];
michaelm@5177 105 }
michaelm@5177 106 }
michaelm@5177 107
michaelm@5177 108 - (void)addNSMenuItemToMenu:(NSMenu *)inMenu {
michaelm@5177 109 if (fMenuItem == nil) return;
michaelm@5177 110 [fMenuItem setSubmenu:fMenu];
michaelm@5177 111 [inMenu addItem:fMenuItem];
michaelm@5177 112 }
michaelm@5177 113
michaelm@5177 114 - (NSMenu *)menu {
michaelm@5177 115 return [[fMenu retain] autorelease];
michaelm@5177 116 }
michaelm@5177 117
michaelm@5177 118 - (void)setNativeEnabled_OnAppKitThread:(NSNumber *)boolNumber {
michaelm@5177 119 AWT_ASSERT_APPKIT_THREAD;
michaelm@5177 120
michaelm@5177 121 @synchronized(self) {
michaelm@5177 122 fIsEnabled = [boolNumber boolValue];
michaelm@5177 123
michaelm@5177 124 NSMenu* supermenu = [fMenu supermenu];
michaelm@5177 125 [[supermenu itemAtIndex:[supermenu indexOfItemWithSubmenu:fMenu]] setEnabled:fIsEnabled];
michaelm@5177 126 }
michaelm@5177 127 }
michaelm@5177 128
michaelm@5177 129 - (NSString *)description {
michaelm@5177 130 return [NSString stringWithFormat:@"CMenu[ %@ ]", fMenu];
michaelm@5177 131 }
michaelm@5177 132
michaelm@5177 133 @end
michaelm@5177 134
michaelm@5177 135 CMenu * createCMenu (jobject cPeerObjGlobal) {
michaelm@5177 136
michaelm@5177 137 CMenu *aCMenu = nil;
michaelm@5177 138
michaelm@5177 139 // We use an array here only to be able to get a return value
michaelm@5177 140 NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
michaelm@5177 141
pchelko@7871 142 [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES];
michaelm@5177 143
michaelm@5177 144 aCMenu = (CMenu *)[args objectAtIndex: 0];
michaelm@5177 145
michaelm@5177 146 if (aCMenu == nil) {
michaelm@5177 147 return 0L;
michaelm@5177 148 }
michaelm@5177 149
michaelm@5177 150 return aCMenu;
michaelm@5177 151
michaelm@5177 152 }
michaelm@5177 153
michaelm@5177 154 /*
michaelm@5177 155 * Class: sun_lwawt_macosx_CMenu
michaelm@5177 156 * Method: nativeCreateSubMenu
michaelm@5177 157 * Signature: (J)J
michaelm@5177 158 */
michaelm@5177 159 JNIEXPORT jlong JNICALL
michaelm@5177 160 Java_sun_lwawt_macosx_CMenu_nativeCreateSubMenu
michaelm@5177 161 (JNIEnv *env, jobject peer, jlong parentMenu)
michaelm@5177 162 {
michaelm@5177 163 CMenu *aCMenu = nil;
michaelm@5177 164 JNF_COCOA_ENTER(env);
michaelm@5177 165
michaelm@5177 166 jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
michaelm@5177 167
michaelm@5177 168 aCMenu = createCMenu (cPeerObjGlobal);
michaelm@5177 169
michaelm@5177 170 // Add it to the parent menu
michaelm@5177 171 [((CMenu *)jlong_to_ptr(parentMenu)) addJavaSubmenu: aCMenu];
michaelm@5177 172 if (aCMenu) {
michaelm@5177 173 CFRetain(aCMenu); // GC
michaelm@5177 174 [aCMenu release];
michaelm@5177 175 }
michaelm@5177 176
michaelm@5177 177 JNF_COCOA_EXIT(env);
michaelm@5177 178
michaelm@5177 179 return ptr_to_jlong(aCMenu);
michaelm@5177 180 }
michaelm@5177 181
michaelm@5177 182
michaelm@5177 183
michaelm@5177 184 /*
michaelm@5177 185 * Class: sun_lwawt_macosx_CMenu
michaelm@5177 186 * Method: nativeCreateMenu
michaelm@5177 187 * Signature: (JZ)J
michaelm@5177 188 */
michaelm@5177 189 JNIEXPORT jlong JNICALL
michaelm@5177 190 Java_sun_lwawt_macosx_CMenu_nativeCreateMenu
michaelm@5177 191 (JNIEnv *env, jobject peer,
michaelm@5177 192 jlong parentMenuBar, jboolean isHelpMenu, jint insertLocation)
michaelm@5177 193 {
michaelm@5177 194 CMenu *aCMenu = nil;
michaelm@5177 195 CMenuBar *parent = (CMenuBar *)jlong_to_ptr(parentMenuBar);
michaelm@5177 196 JNF_COCOA_ENTER(env);
michaelm@5177 197
michaelm@5177 198 jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
michaelm@5177 199
michaelm@5177 200 aCMenu = createCMenu (cPeerObjGlobal);
michaelm@5177 201
michaelm@5177 202 // Add it to the menu bar.
michaelm@5177 203 [parent javaAddMenu:aCMenu atIndex:insertLocation];
michaelm@5177 204
michaelm@5177 205 // If the menu is already the help menu (because we are creating an entire
michaelm@5177 206 // menu bar) we need to note that now, because we can't rely on
michaelm@5177 207 // setHelpMenu() being called again.
michaelm@5177 208 if (isHelpMenu == JNI_TRUE) {
michaelm@5177 209 [parent javaSetHelpMenu: aCMenu];
michaelm@5177 210 }
michaelm@5177 211
michaelm@5177 212 if (aCMenu) {
michaelm@5177 213 CFRetain(aCMenu); // GC
michaelm@5177 214 [aCMenu release];
michaelm@5177 215 }
michaelm@5177 216 JNF_COCOA_EXIT(env);
michaelm@5177 217 return ptr_to_jlong(aCMenu);
michaelm@5177 218 }
michaelm@5177 219
michaelm@5177 220
michaelm@5177 221 /*
michaelm@5177 222 * Class: sun_lwawt_macosx_CMenu
michaelm@5177 223 * Method: nativeSetMenuTitle
michaelm@5177 224 * Signature: (JLjava/lang/String;)V
michaelm@5177 225 */
michaelm@5177 226 JNIEXPORT void JNICALL
michaelm@5177 227 Java_sun_lwawt_macosx_CMenu_nativeSetMenuTitle
michaelm@5177 228 (JNIEnv *env, jobject peer, jlong menuObject, jstring label)
michaelm@5177 229 {
michaelm@5177 230 JNF_COCOA_ENTER(env);
michaelm@5177 231 // Set the menu's title.
michaelm@5177 232 [((CMenu *)jlong_to_ptr(menuObject)) setJavaMenuTitle:JNFJavaToNSString(env, label)];
michaelm@5177 233 JNF_COCOA_EXIT(env);
michaelm@5177 234 }
michaelm@5177 235
michaelm@5177 236 /*
michaelm@5177 237 * Class: sun_lwawt_macosx_CMenu
michaelm@5177 238 * Method: nativeAddSeparator
michaelm@5177 239 * Signature: (J)V
michaelm@5177 240 */
michaelm@5177 241 JNIEXPORT void JNICALL
michaelm@5177 242 Java_sun_lwawt_macosx_CMenu_nativeAddSeparator
michaelm@5177 243 (JNIEnv *env, jobject peer, jlong menuObject)
michaelm@5177 244 {
michaelm@5177 245 JNF_COCOA_ENTER(env);
michaelm@5177 246 // Add a separator item.
michaelm@5177 247 [((CMenu *)jlong_to_ptr(menuObject))addSeparator];
michaelm@5177 248 JNF_COCOA_EXIT(env);
michaelm@5177 249 }
michaelm@5177 250
michaelm@5177 251 /*
michaelm@5177 252 * Class: sun_lwawt_macosx_CMenu
michaelm@5177 253 * Method: nativeDeleteItem
michaelm@5177 254 * Signature: (JI)V
michaelm@5177 255 */
michaelm@5177 256 JNIEXPORT void JNICALL
michaelm@5177 257 Java_sun_lwawt_macosx_CMenu_nativeDeleteItem
michaelm@5177 258 (JNIEnv *env, jobject peer, jlong menuObject, jint index)
michaelm@5177 259 {
michaelm@5177 260 JNF_COCOA_ENTER(env);
michaelm@5177 261 // Remove the specified item.
michaelm@5177 262 [((CMenu *)jlong_to_ptr(menuObject)) deleteJavaItem: index];
michaelm@5177 263 JNF_COCOA_EXIT(env);
michaelm@5177 264 }
michaelm@5177 265
michaelm@5177 266 /*
michaelm@5177 267 * Class: sun_lwawt_macosx_CMenu
michaelm@5177 268 * Method: nativeGetNSMenu
michaelm@5177 269 * Signature: (J)J
michaelm@5177 270 */
michaelm@5177 271 JNIEXPORT jlong JNICALL
michaelm@5177 272 Java_sun_lwawt_macosx_CMenu_nativeGetNSMenu
michaelm@5177 273 (JNIEnv *env, jobject peer, jlong menuObject)
michaelm@5177 274 {
michaelm@5177 275 NSMenu* nsMenu = NULL;
michaelm@5177 276
michaelm@5177 277 JNF_COCOA_ENTER(env);
michaelm@5177 278 nsMenu = [((CMenu *)jlong_to_ptr(menuObject)) menu];
michaelm@5177 279 JNF_COCOA_EXIT(env);
michaelm@5177 280
michaelm@5177 281 // Strong retain this menu; it'll get released in Java_apple_laf_ScreenMenu_addMenuListeners
michaelm@5177 282 if (nsMenu) {
michaelm@5177 283 CFRetain(nsMenu); // GC
michaelm@5177 284 }
michaelm@5177 285
michaelm@5177 286 return ptr_to_jlong(nsMenu);
michaelm@5177 287 }