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 #import "ApplicationDelegate.h" 27 28 #import "com_apple_eawt_Application.h" 29 #import "com_apple_eawt__AppDockIconHandler.h" 30 #import "com_apple_eawt__AppEventHandler.h" 31 #import "com_apple_eawt__AppMenuBarHandler.h" 32 #import "com_apple_eawt__AppMenuBarHandler.h" 33 #import "com_apple_eawt__AppMiscHandlers.h" 34 35 #import <JavaNativeFoundation/JavaNativeFoundation.h> 36 37 #import "CPopupMenu.h" 38 #import "ThreadUtilities.h" 39 #import "NSApplicationAWT.h" 40 41 42 #pragma mark App Menu helpers 43 44 // The following is a AWT convention? 45 #define PREFERENCES_TAG 42 46 47 static void addMenuItem(NSMenuItem* menuItem, NSInteger index) { 48 AWT_ASSERT_APPKIT_THREAD; 49 50 NSMenu *menuBar = [[NSApplication sharedApplication] mainMenu]; 51 NSMenu *appMenu = [[menuBar itemAtIndex:0] submenu]; 52 53 [appMenu insertItem:menuItem atIndex:index]; 54 [appMenu insertItem:[NSMenuItem separatorItem] atIndex:index + 1]; // Add the following separator 55 } 56 57 static void removeMenuItem(NSMenuItem* menuItem) { 58 AWT_ASSERT_APPKIT_THREAD; 59 60 NSMenu *menuBar = [[NSApplication sharedApplication] mainMenu]; 61 NSMenu *appMenu = [[menuBar itemAtIndex:0] submenu]; 62 63 NSInteger index = [appMenu indexOfItem:menuItem]; 64 if (index < 0) return; // something went wrong 65 66 [appMenu removeItemAtIndex:index + 1]; // Get the following separator 67 [appMenu removeItem:menuItem]; 68 } 69 70 @interface NSBundle (EAWTOverrides) 71 - (BOOL)_hasEAWTOverride:(NSString *)key; 72 @end 73 74 75 @implementation NSBundle (EAWTOverrides) 76 77 - (BOOL)_hasEAWTOverride:(NSString *)key { 78 return [[[[self objectForInfoDictionaryKey:@"Java"] objectForKey:@"EAWTOverride"] objectForKey:key] boolValue]; 79 } 80 81 @end 82 83 84 // used by JavaRuntimeSupport.framework's [JRSAppKitAWT awtAppDelegate] 85 // to expose our app delegate to the SWT or other apps that have knoledge 86 // of Java's AWT and want to install their own app delegate that will delegate 87 // to the AWT for some operations 88 89 @interface JavaAWTAppDelegateLoader : NSObject { } 90 @end 91 92 @implementation JavaAWTAppDelegateLoader 93 + (ApplicationDelegate *) awtAppDelegate { 94 return [ApplicationDelegate sharedDelegate]; 95 } 96 @end 97 98 99 @implementation ApplicationDelegate 100 101 @synthesize fPreferencesMenu; 102 @synthesize fAboutMenu; 103 104 @synthesize fDockMenu; 105 @synthesize fDefaultMenuBar; 106 107 108 + (ApplicationDelegate *)sharedDelegate { 109 static ApplicationDelegate *sApplicationDelegate = nil; 110 static BOOL checked = NO; 111 112 if (sApplicationDelegate != nil) return sApplicationDelegate; 113 if (checked) return nil; 114 115 AWT_ASSERT_APPKIT_THREAD; 116 117 // don't install the EAWT delegate if another kind of NSApplication is installed, like say, Safari 118 BOOL shouldInstall = NO; 119 if (NSApp != nil) { 120 if ([NSApp isMemberOfClass:[NSApplication class]]) shouldInstall = YES; 121 if ([NSApp isKindOfClass:[NSApplicationAWT class]]) shouldInstall = YES; 122 } 123 checked = YES; 124 if (!shouldInstall) return nil; 125 126 sApplicationDelegate = [[ApplicationDelegate alloc] init]; 127 return sApplicationDelegate; 128 } 129 130 - (void)_updatePreferencesMenu:(BOOL)prefsAvailable enabled:(BOOL)prefsEnabled { 131 AWT_ASSERT_APPKIT_THREAD; 132 133 if (prefsAvailable) { 134 // Make sure Prefs is around 135 if ([self.fPreferencesMenu menu] == nil) { 136 // Position of Prefs depends upon About availability. 137 NSInteger index = ([self.fAboutMenu menu] != nil) ? 2 : 0; 138 139 addMenuItem(self.fPreferencesMenu, index); 140 } 141 142 if (prefsEnabled) { 143 [self.fPreferencesMenu setEnabled:YES]; 144 [self.fPreferencesMenu setTarget:self]; 145 [self.fPreferencesMenu setAction:@selector(_preferencesMenuHandler)]; 146 } else { 147 [self.fPreferencesMenu setEnabled:NO]; 148 [self.fPreferencesMenu setTarget:nil]; 149 [self.fPreferencesMenu setAction:nil]; 150 } 151 } else { 152 if ([self.fPreferencesMenu menu] == nil) return; 153 154 // Remove the preferences item 155 removeMenuItem(self.fPreferencesMenu); 156 } 157 } 158 159 - (void)_updateAboutMenu:(BOOL)aboutAvailable enabled:(BOOL)aboutEnabled { 160 AWT_ASSERT_APPKIT_THREAD; 161 162 if (aboutAvailable) { 163 // Make sure About is around 164 if ([self.fAboutMenu menu] == nil) { 165 addMenuItem(self.fAboutMenu, 0); 166 } 167 168 if (aboutEnabled) { 169 [self.fAboutMenu setEnabled:YES]; 170 [self.fAboutMenu setTarget:self]; 171 [self.fAboutMenu setAction:@selector(_aboutMenuHandler)]; 172 } else { 173 [self.fAboutMenu setEnabled:NO]; 174 [self.fAboutMenu setTarget:nil]; 175 [self.fAboutMenu setAction:nil]; 176 } 177 } else { 178 if ([self.fAboutMenu menu] == nil) return; 179 180 // Remove About item. 181 removeMenuItem(self.fAboutMenu); 182 } 183 } 184 185 - (id) init { 186 AWT_ASSERT_APPKIT_THREAD; 187 188 self = [super init]; 189 if (!self) return self; 190 191 // Prep for about and preferences menu 192 BOOL usingDefaultNib = YES; 193 if ([NSApp isKindOfClass:[NSApplicationAWT class]]) { 194 usingDefaultNib = [NSApp usingDefaultNib]; 195 } 196 if (!usingDefaultNib) return self; 197 198 NSMenu *menuBar = [[NSApplication sharedApplication] mainMenu]; 199 NSMenu *appMenu = [[menuBar itemAtIndex:0] submenu]; 200 201 self.fPreferencesMenu = (NSMenuItem*)[appMenu itemWithTag:PREFERENCES_TAG]; 202 self.fAboutMenu = (NSMenuItem*)[appMenu itemAtIndex:0]; 203 204 // If the java application has a bundle with an Info.plist file with 205 // a CFBundleDocumentTypes entry, then it is set up to handle Open Doc 206 // and Print Doc commands for these files. Therefore java AWT will 207 // cache Open Doc and Print Doc events that are sent prior to a 208 // listener being installed by the client java application. 209 NSBundle *bundle = [NSBundle mainBundle]; 210 fHandlesDocumentTypes = [bundle objectForInfoDictionaryKey:@"CFBundleDocumentTypes"] != nil || [bundle _hasEAWTOverride:@"DocumentHandler"]; 211 fHandlesURLTypes = [bundle objectForInfoDictionaryKey:@"CFBundleURLTypes"] != nil || [bundle _hasEAWTOverride:@"URLHandler"]; 212 if (fHandlesURLTypes) { 213 [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self 214 andSelector:@selector(_handleOpenURLEvent:withReplyEvent:) 215 forEventClass:kInternetEventClass 216 andEventID:kAEGetURL]; 217 } 218 219 // By HIG, Preferences are not available unless there is a handler. By default in Mac OS X, 220 // there is not a handler, but it is in the nib file for convenience. 221 removeMenuItem(self.fPreferencesMenu); 222 223 [self _updateAboutMenu:YES enabled:YES]; 224 225 // Now that the AppKit objects are known and set up, initialize the model data 226 BOOL aboutAvailable = ([self.fAboutMenu menu] != nil); 227 BOOL aboutEnabled = (aboutAvailable && [self.fAboutMenu isEnabled] && ([self.fAboutMenu target] != nil)); 228 229 BOOL prefsAvailable = ([self.fPreferencesMenu menu] != nil); 230 BOOL prefsEnabled = (prefsAvailable && [self.fPreferencesMenu isEnabled] && ([self.fPreferencesMenu target] != nil)); 231 232 JNIEnv *env = [ThreadUtilities getJNIEnv]; 233 static JNF_CLASS_CACHE(sjc_AppMenuBarHandler, "com/apple/eawt/_AppMenuBarHandler"); 234 static JNF_STATIC_MEMBER_CACHE(sjm_initMenuStates, sjc_AppMenuBarHandler, "initMenuStates", "(ZZZZ)V"); 235 JNFCallStaticVoidMethod(env, sjm_initMenuStates, aboutAvailable, aboutEnabled, prefsAvailable, prefsEnabled); 236 237 // register for the finish launching and system power off notifications by default 238 NSNotificationCenter *ctr = [NSNotificationCenter defaultCenter]; 239 Class clz = [ApplicationDelegate class]; 240 [ctr addObserver:clz selector:@selector(_willFinishLaunching) name:NSApplicationWillFinishLaunchingNotification object:nil]; 241 [ctr addObserver:clz selector:@selector(_systemWillPowerOff) name:NSWorkspaceWillPowerOffNotification object:nil]; 242 [ctr addObserver:clz selector:@selector(_appDidActivate) name:NSApplicationDidBecomeActiveNotification object:nil]; 243 [ctr addObserver:clz selector:@selector(_appDidDeactivate) name:NSApplicationDidResignActiveNotification object:nil]; 244 [ctr addObserver:clz selector:@selector(_appDidHide) name:NSApplicationDidHideNotification object:nil]; 245 [ctr addObserver:clz selector:@selector(_appDidUnhide) name:NSApplicationDidUnhideNotification object:nil]; 246 247 return self; 248 } 249 250 - (void)dealloc { 251 self.fPreferencesMenu = nil; 252 self.fAboutMenu = nil; 253 self.fDockMenu = nil; 254 self.fDefaultMenuBar = nil; 255 256 [super dealloc]; 257 } 258 //- (void)finalize { [super finalize]; } // GC 259 260 261 #pragma mark Callbacks from AppKit 262 263 static JNF_CLASS_CACHE(sjc_AppEventHandler, "com/apple/eawt/_AppEventHandler"); 264 265 - (void)_handleOpenURLEvent:(NSAppleEventDescriptor *)openURLEvent withReplyEvent:(NSAppleEventDescriptor *)replyEvent { 266 AWT_ASSERT_APPKIT_THREAD; 267 if (!fHandlesURLTypes) return; 268 269 NSString *url = [[openURLEvent paramDescriptorForKeyword:keyDirectObject] stringValue]; 270 271 //fprintf(stderr,"jm_handleOpenURL\n"); 272 JNIEnv *env = [ThreadUtilities getJNIEnv]; 273 jstring jURL = JNFNSToJavaString(env, url); 274 static JNF_STATIC_MEMBER_CACHE(jm_handleOpenURI, sjc_AppEventHandler, "handleOpenURI", "(Ljava/lang/String;)V"); 275 JNFCallStaticVoidMethod(env, jm_handleOpenURI, jURL); // AWT_THREADING Safe (event) 276 (*env)->DeleteLocalRef(env, jURL); 277 278 [replyEvent insertDescriptor:[NSAppleEventDescriptor nullDescriptor] atIndex:0]; 279 } 280 281 // Helper for both open file and print file methods 282 // Creates a Java list of files from a native list of files 283 - (jobject)_createFilePathArrayFrom:(NSArray *)filenames withEnv:(JNIEnv *)env { 284 static JNF_CLASS_CACHE(sjc_ArrayList, "java/util/ArrayList"); 285 static JNF_CTOR_CACHE(jm_ArrayList_ctor, sjc_ArrayList, "(I)V"); 286 static JNF_MEMBER_CACHE(jm_ArrayList_add, sjc_ArrayList, "add", "(Ljava/lang/Object;)Z"); 287 288 jobject jFileNamesArray = JNFNewObject(env, jm_ArrayList_ctor, (jint)[filenames count]); // AWT_THREADING Safe (known object) 289 for (NSString *filename in filenames) { 290 jstring jFileName = JNFNormalizedJavaStringForPath(env, filename); 291 JNFCallVoidMethod(env, jFileNamesArray, jm_ArrayList_add, jFileName); 292 } 293 294 return jFileNamesArray; 295 } 296 297 // Open file handler 298 - (void)application:(NSApplication *)theApplication openFiles:(NSArray *)fileNames { 299 AWT_ASSERT_APPKIT_THREAD; 300 if (!fHandlesDocumentTypes) { 301 [theApplication replyToOpenOrPrint:NSApplicationDelegateReplyCancel]; 302 return; 303 } 304 305 //fprintf(stderr,"jm_handleOpenFile\n"); 306 JNIEnv *env = [ThreadUtilities getJNIEnv]; 307 308 // if these files were opened from a Spotlight query, try to get the search text from the current AppleEvent 309 NSAppleEventDescriptor *currentEvent = [[NSAppleEventManager sharedAppleEventManager] currentAppleEvent]; 310 NSString *searchString = [[currentEvent paramDescriptorForKeyword:keyAESearchText] stringValue]; 311 jstring jSearchString = JNFNSToJavaString(env, searchString); 312 313 // convert the file names array 314 jobject jFileNamesArray = [self _createFilePathArrayFrom:fileNames withEnv:env]; 315 316 static JNF_STATIC_MEMBER_CACHE(jm_handleOpenFiles, sjc_AppEventHandler, "handleOpenFiles", "(Ljava/util/List;Ljava/lang/String;)V"); 317 JNFCallStaticVoidMethod(env, jm_handleOpenFiles, jFileNamesArray, jSearchString); 318 (*env)->DeleteLocalRef(env, jFileNamesArray); 319 (*env)->DeleteLocalRef(env, jSearchString); 320 321 [theApplication replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; 322 } 323 324 // Print handler 325 - (NSApplicationPrintReply)application:(NSApplication *)application printFiles:(NSArray *)fileNames withSettings:(NSDictionary *)printSettings showPrintPanels:(BOOL)showPrintPanels { 326 AWT_ASSERT_APPKIT_THREAD; 327 if (!fHandlesDocumentTypes) return NSPrintingCancelled; 328 329 //fprintf(stderr,"jm_handlePrintFile\n"); 330 JNIEnv *env = [ThreadUtilities getJNIEnv]; 331 jobject jFileNamesArray = [self _createFilePathArrayFrom:fileNames withEnv:env]; 332 static JNF_STATIC_MEMBER_CACHE(jm_handlePrintFile, sjc_AppEventHandler, "handlePrintFiles", "(Ljava/util/List;)V"); 333 JNFCallStaticVoidMethod(env, jm_handlePrintFile, jFileNamesArray); // AWT_THREADING Safe (event) 334 (*env)->DeleteLocalRef(env, jFileNamesArray); 335 336 return NSPrintingSuccess; 337 } 338 339 // Open app handler, registered in -init 340 + (void)_notifyJava:(jint)notificationType { 341 AWT_ASSERT_APPKIT_THREAD; 342 343 //fprintf(stderr,"jm_handleOpenApplication\n"); 344 JNIEnv *env = [ThreadUtilities getJNIEnv]; 345 static JNF_STATIC_MEMBER_CACHE(jm_handleNativeNotification, sjc_AppEventHandler, "handleNativeNotification", "(I)V"); 346 JNFCallStaticVoidMethod(env, jm_handleNativeNotification, notificationType); // AWT_THREADING Safe (event) 347 } 348 349 // About menu handler 350 - (void)_aboutMenuHandler { 351 [ApplicationDelegate _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_ABOUT]; 352 } 353 354 // Preferences handler 355 - (void)_preferencesMenuHandler { 356 [ApplicationDelegate _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_PREFS]; 357 } 358 359 // Open app handler, registered in -init 360 + (void)_willFinishLaunching { 361 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_OPEN_APP]; 362 } 363 364 // ReOpen app handler 365 - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag { 366 [ApplicationDelegate _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_REOPEN_APP]; 367 return YES; 368 } 369 370 // Quit handler 371 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app { 372 [ApplicationDelegate _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_QUIT]; 373 return NSTerminateLater; 374 } 375 376 + (void)_systemWillPowerOff { 377 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_SHUTDOWN]; 378 } 379 380 + (void)_appDidActivate { 381 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_ACTIVE_APP_GAINED]; 382 } 383 384 + (void)_appDidDeactivate { 385 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_ACTIVE_APP_LOST]; 386 } 387 388 + (void)_appDidHide { 389 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_APP_HIDDEN]; 390 } 391 392 + (void)_appDidUnhide { 393 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_APP_SHOWN]; 394 } 395 396 + (void)_sessionDidActivate { 397 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_USER_SESSION_ACTIVE]; 398 } 399 400 + (void)_sessionDidDeactivate { 401 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_USER_SESSION_INACTIVE]; 402 } 403 404 + (void)_screenDidSleep { 405 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_SCREEN_SLEEP]; 406 } 407 408 + (void)_screenDidWake { 409 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_SCREEN_WAKE]; 410 } 411 412 + (void)_systemDidSleep { 413 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_SYSTEM_SLEEP]; 414 } 415 416 + (void)_systemDidWake { 417 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_SYSTEM_WAKE]; 418 } 419 420 + (void)_registerForNotification:(NSNumber *)notificationTypeNum { 421 NSNotificationCenter *ctr = [[NSWorkspace sharedWorkspace] notificationCenter]; 422 Class clz = [ApplicationDelegate class]; 423 424 jint notificationType = [notificationTypeNum intValue]; 425 switch (notificationType) { 426 case com_apple_eawt__AppEventHandler_REGISTER_USER_SESSION: 427 [ctr addObserver:clz selector:@selector(_sessionDidActivate) name:NSWorkspaceSessionDidBecomeActiveNotification object:nil]; 428 [ctr addObserver:clz selector:@selector(_sessionDidDeactivate) name:NSWorkspaceSessionDidResignActiveNotification object:nil]; 429 break; 430 case com_apple_eawt__AppEventHandler_REGISTER_SCREEN_SLEEP: 431 [ctr addObserver:clz selector:@selector(_screenDidSleep) name:NSWorkspaceScreensDidSleepNotification object:nil]; 432 [ctr addObserver:clz selector:@selector(_screenDidWake) name:NSWorkspaceScreensDidWakeNotification object:nil]; 433 break; 434 case com_apple_eawt__AppEventHandler_REGISTER_SYSTEM_SLEEP: 435 [ctr addObserver:clz selector:@selector(_systemDidSleep) name:NSWorkspaceWillSleepNotification object:nil]; 436 [ctr addObserver:clz selector:@selector(_systemDidWake) name:NSWorkspaceDidWakeNotification object:nil]; 437 break; 438 default: 439 NSLog(@"EAWT attempting to register for unknown notification: %d", (int)notificationType); 440 break; 441 } 442 } 443 444 // Retrieves the menu to be attached to the Dock icon (AppKit callback) 445 - (NSMenu *)applicationDockMenu:(NSApplication *)sender { 446 AWT_ASSERT_APPKIT_THREAD; 447 return self.fDockMenu; 448 } 449 450 - (CMenuBar *)defaultMenuBar { 451 return [[self.fDefaultMenuBar retain] autorelease]; 452 } 453 454 455 #pragma mark Helpers called on the main thread from Java 456 457 // Sets a new NSImageView on the Dock tile 458 + (void)_setDockIconImage:(NSImage *)image { 459 AWT_ASSERT_APPKIT_THREAD; 460 461 NSDockTile *dockTile = [NSApp dockTile]; 462 if (image == nil) { 463 [dockTile setContentView:nil]; 464 return; 465 } 466 467 // setup an image view for the dock tile 468 NSRect frame = NSMakeRect(0, 0, dockTile.size.width, dockTile.size.height); 469 NSImageView *dockImageView = [[NSImageView alloc] initWithFrame: frame]; 470 [dockImageView setImageScaling:NSImageScaleProportionallyUpOrDown]; 471 [dockImageView setImage:image]; 472 473 // add it to the NSDockTile 474 [dockTile setContentView: dockImageView]; 475 [dockTile display]; 476 477 [dockImageView release]; 478 } 479 480 // Obtains the image of the Dock icon, either manually set, a drawn copy, or the default NSApplicationIcon 481 + (NSImage *)_dockIconImage { 482 AWT_ASSERT_APPKIT_THREAD; 483 484 NSDockTile *dockTile = [NSApp dockTile]; 485 NSView *view = [dockTile contentView]; 486 487 if ([view isKindOfClass:[NSImageView class]]) { 488 NSImage *img = [((NSImageView *)view) image]; 489 if (img) return img; 490 } 491 492 if (view == nil) { 493 return [NSImage imageNamed:@"NSApplicationIcon"]; 494 } 495 496 NSRect frame = [view frame]; 497 NSImage *image = [[NSImage alloc] initWithSize:frame.size]; 498 [image lockFocus]; 499 [view drawRect:frame]; 500 [image unlockFocus]; 501 [image autorelease]; 502 return image; 503 } 504 505 @end 506 507 508 #pragma mark Native JNI calls 509 510 /* 511 * Class: com_apple_eawt_Application 512 * Method: nativeInitializeApplicationDelegate 513 * Signature: ()V 514 */ 515 JNIEXPORT void JNICALL Java_com_apple_eawt_Application_nativeInitializeApplicationDelegate 516 (JNIEnv *env, jclass clz) 517 { 518 JNF_COCOA_ENTER(env); 519 // Force initialization to happen on AppKit thread! 520 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 521 [ApplicationDelegate sharedDelegate]; 522 }]; 523 JNF_COCOA_EXIT(env); 524 } 525 526 /* 527 * Class: com_apple_eawt__AppEventHandler 528 * Method: nativeOpenCocoaAboutWindow 529 * Signature: ()V 530 */ 531 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeOpenCocoaAboutWindow 532 (JNIEnv *env, jclass clz) 533 { 534 JNF_COCOA_ENTER(env); 535 536 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 537 [NSApp orderFrontStandardAboutPanel:nil]; 538 }]; 539 540 JNF_COCOA_EXIT(env); 541 } 542 543 /* 544 * Class: com_apple_eawt__AppEventHandler 545 * Method: nativeReplyToAppShouldTerminate 546 * Signature: (Z)V 547 */ 548 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeReplyToAppShouldTerminate 549 (JNIEnv *env, jclass clz, jboolean doTerminate) 550 { 551 JNF_COCOA_ENTER(env); 552 553 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 554 [NSApp replyToApplicationShouldTerminate:doTerminate]; 555 }]; 556 557 JNF_COCOA_EXIT(env); 558 } 559 560 /* 561 * Class: com_apple_eawt__AppEventHandler 562 * Method: nativeRegisterForNotification 563 * Signature: (I)V 564 */ 565 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeRegisterForNotification 566 (JNIEnv *env, jclass clz, jint notificationType) 567 { 568 JNF_COCOA_ENTER(env); 569 [ThreadUtilities performOnMainThread:@selector(_registerForNotification:) 570 on:[ApplicationDelegate class] 571 withObject:[NSNumber numberWithInt:notificationType] 572 waitUntilDone:NO]; // AWT_THREADING Safe (non-blocking) 573 JNF_COCOA_EXIT(env); 574 } 575 576 /* 577 * Class: com_apple_eawt__AppDockIconHandler 578 * Method: nativeSetDockMenu 579 * Signature: (J)V 580 */ 581 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockMenu 582 (JNIEnv *env, jclass clz, jlong nsMenuPtr) 583 { 584 JNF_COCOA_ENTER(env); 585 586 NSMenu *menu = (NSMenu *)jlong_to_ptr(nsMenuPtr); 587 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 588 [ApplicationDelegate sharedDelegate].fDockMenu = menu; 589 }]; 590 591 JNF_COCOA_EXIT(env); 592 } 593 594 /* 595 * Class: com_apple_eawt__AppDockIconHandler 596 * Method: nativeSetDockIconImage 597 * Signature: (J)V 598 */ 599 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockIconImage 600 (JNIEnv *env, jclass clz, jlong nsImagePtr) 601 { 602 JNF_COCOA_ENTER(env); 603 604 NSImage *_image = (NSImage *)jlong_to_ptr(nsImagePtr); 605 [ThreadUtilities performOnMainThread:@selector(_setDockIconImage:) 606 on:[ApplicationDelegate class] 607 withObject:_image 608 waitUntilDone:NO]; 609 610 JNF_COCOA_EXIT(env); 611 } 612 613 /* 614 * Class: com_apple_eawt__AppDockIconHandler 615 * Method: nativeGetDockIconImage 616 * Signature: ()J 617 */ 618 JNIEXPORT jlong JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeGetDockIconImage 619 (JNIEnv *env, jclass clz) 620 { 621 __block NSImage *image = nil; 622 623 JNF_COCOA_ENTER(env); 624 625 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 626 image = [ApplicationDelegate _dockIconImage]; 627 CFRetain(image); 628 }]; 629 630 JNF_COCOA_EXIT(env); 631 632 return ptr_to_jlong(image); 633 } 634 635 /* 636 * Class: com_apple_eawt__AppDockIconHandler 637 * Method: nativeSetDockIconBadge 638 * Signature: (Ljava/lang/String;)V 639 */ 640 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockIconBadge 641 (JNIEnv *env, jclass clz, jstring badge) 642 { 643 JNF_COCOA_ENTER(env); 644 645 NSString *badgeString = JNFJavaToNSString(env, badge); 646 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 647 NSDockTile *dockTile = [NSApp dockTile]; 648 [dockTile setBadgeLabel:badgeString]; 649 [dockTile display]; 650 }]; 651 652 JNF_COCOA_EXIT(env); 653 } 654 655 /* 656 * Class: com_apple_eawt__AppMiscHandlers 657 * Method: nativeRequestActivation 658 * Signature: (Z)V 659 */ 660 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeRequestActivation 661 (JNIEnv *env, jclass clz, jboolean allWindows) 662 { 663 JNF_COCOA_ENTER(env); 664 665 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 666 NSApplicationActivationOptions options = allWindows ? NSApplicationActivateAllWindows : 0; 667 options |= NSApplicationActivateIgnoringOtherApps; // without this, nothing happens! 668 [[NSRunningApplication currentApplication] activateWithOptions:options]; 669 }]; 670 671 JNF_COCOA_EXIT(env); 672 } 673 674 /* 675 * Class: com_apple_eawt__AppMiscHandlers 676 * Method: nativeRequestUserAttention 677 * Signature: (Z)V 678 */ 679 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeRequestUserAttention 680 (JNIEnv *env, jclass clz, jboolean critical) 681 { 682 JNF_COCOA_ENTER(env); 683 684 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 685 [NSApp requestUserAttention:critical ? NSCriticalRequest : NSInformationalRequest]; 686 }]; 687 688 JNF_COCOA_EXIT(env); 689 } 690 691 /* 692 * Class: com_apple_eawt__AppMiscHandlers 693 * Method: nativeOpenHelpViewer 694 * Signature: ()V 695 */ 696 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeOpenHelpViewer 697 (JNIEnv *env, jclass clz) 698 { 699 JNF_COCOA_ENTER(env); 700 701 [ThreadUtilities performOnMainThread:@selector(showHelp:) 702 on:NSApp 703 withObject:nil 704 waitUntilDone:NO]; 705 706 JNF_COCOA_EXIT(env); 707 } 708 709 /* 710 * Class: com_apple_eawt__AppMiscHandlers 711 * Method: nativeEnableSuddenTermination 712 * Signature: ()V 713 */ 714 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeEnableSuddenTermination 715 (JNIEnv *env, jclass clz) 716 { 717 JNF_COCOA_ENTER(env); 718 719 [[NSProcessInfo processInfo] enableSuddenTermination]; // Foundation thread-safe 720 721 JNF_COCOA_EXIT(env); 722 } 723 724 /* 725 * Class: com_apple_eawt__AppMiscHandlers 726 * Method: nativeDisableSuddenTermination 727 * Signature: ()V 728 */ 729 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeDisableSuddenTermination 730 (JNIEnv *env, jclass clz) 731 { 732 JNF_COCOA_ENTER(env); 733 734 [[NSProcessInfo processInfo] disableSuddenTermination]; // Foundation thread-safe 735 736 JNF_COCOA_EXIT(env); 737 } 738 739 /* 740 * Class: com_apple_eawt__AppMenuBarHandler 741 * Method: nativeSetMenuState 742 * Signature: (IZZ)V 743 */ 744 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMenuBarHandler_nativeSetMenuState 745 (JNIEnv *env, jclass clz, jint menuID, jboolean visible, jboolean enabled) 746 { 747 JNF_COCOA_ENTER(env); 748 749 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 750 ApplicationDelegate *delegate = [ApplicationDelegate sharedDelegate]; 751 switch (menuID) { 752 case com_apple_eawt__AppMenuBarHandler_MENU_ABOUT: 753 [delegate _updateAboutMenu:visible enabled:enabled]; 754 break; 755 case com_apple_eawt__AppMenuBarHandler_MENU_PREFS: 756 [delegate _updatePreferencesMenu:visible enabled:enabled]; 757 break; 758 } 759 }]; 760 761 JNF_COCOA_EXIT(env); 762 } 763 764 /* 765 * Class: com_apple_eawt__AppMenuBarHandler 766 * Method: nativeSetDefaultMenuBar 767 * Signature: (J)V 768 */ 769 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMenuBarHandler_nativeSetDefaultMenuBar 770 (JNIEnv *env, jclass clz, jlong cMenuBarPtr) 771 { 772 JNF_COCOA_ENTER(env); 773 774 CMenuBar *menu = (CMenuBar *)jlong_to_ptr(cMenuBarPtr); 775 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 776 [ApplicationDelegate sharedDelegate].fDefaultMenuBar = menu; 777 }]; 778 779 JNF_COCOA_EXIT(env); 780 }