1 /* 2 * Copyright (c) 2011, 2014, 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 @synthesize isAppActive; 107 108 109 + (ApplicationDelegate *)sharedDelegate { 110 static ApplicationDelegate *sApplicationDelegate = nil; 111 static BOOL checked = NO; 112 113 if (sApplicationDelegate != nil) return sApplicationDelegate; 114 if (checked) return nil; 115 116 AWT_ASSERT_APPKIT_THREAD; 117 118 // don't install the EAWT delegate if another kind of NSApplication is installed, like say, Safari 119 BOOL shouldInstall = NO; 120 if (NSApp != nil) { 121 if ([NSApp isMemberOfClass:[NSApplication class]]) shouldInstall = YES; 122 if ([NSApp isKindOfClass:[NSApplicationAWT class]]) shouldInstall = YES; 123 } 124 checked = YES; 125 if (!shouldInstall) return nil; 126 127 sApplicationDelegate = [[ApplicationDelegate alloc] init]; 128 return sApplicationDelegate; 129 } 130 131 - (void)_updatePreferencesMenu:(BOOL)prefsAvailable enabled:(BOOL)prefsEnabled { 132 AWT_ASSERT_APPKIT_THREAD; 133 134 if (prefsAvailable) { 135 // Make sure Prefs is around 136 if ([self.fPreferencesMenu menu] == nil) { 137 // Position of Prefs depends upon About availability. 138 NSInteger index = ([self.fAboutMenu menu] != nil) ? 2 : 0; 139 140 addMenuItem(self.fPreferencesMenu, index); 141 } 142 143 if (prefsEnabled) { 144 [self.fPreferencesMenu setEnabled:YES]; 145 [self.fPreferencesMenu setTarget:self]; 146 [self.fPreferencesMenu setAction:@selector(_preferencesMenuHandler)]; 147 } else { 148 [self.fPreferencesMenu setEnabled:NO]; 149 [self.fPreferencesMenu setTarget:nil]; 150 [self.fPreferencesMenu setAction:nil]; 151 } 152 } else { 153 if ([self.fPreferencesMenu menu] == nil) return; 154 155 // Remove the preferences item 156 removeMenuItem(self.fPreferencesMenu); 157 } 158 } 159 160 - (void)_updateAboutMenu:(BOOL)aboutAvailable enabled:(BOOL)aboutEnabled { 161 AWT_ASSERT_APPKIT_THREAD; 162 163 if (aboutAvailable) { 164 // Make sure About is around 165 if ([self.fAboutMenu menu] == nil) { 166 addMenuItem(self.fAboutMenu, 0); 167 } 168 169 if (aboutEnabled) { 170 [self.fAboutMenu setEnabled:YES]; 171 [self.fAboutMenu setTarget:self]; 172 [self.fAboutMenu setAction:@selector(_aboutMenuHandler)]; 173 } else { 174 [self.fAboutMenu setEnabled:NO]; 175 [self.fAboutMenu setTarget:nil]; 176 [self.fAboutMenu setAction:nil]; 177 } 178 } else { 179 if ([self.fAboutMenu menu] == nil) return; 180 181 // Remove About item. 182 removeMenuItem(self.fAboutMenu); 183 } 184 } 185 186 - (id) init { 187 AWT_ASSERT_APPKIT_THREAD; 188 189 self = [super init]; 190 if (!self) return self; 191 192 // Prep for about and preferences menu 193 BOOL usingDefaultNib = YES; 194 if ([NSApp isKindOfClass:[NSApplicationAWT class]]) { 195 usingDefaultNib = [NSApp usingDefaultNib]; 196 } 197 if (!usingDefaultNib) return self; 198 199 NSMenu *menuBar = [[NSApplication sharedApplication] mainMenu]; 200 NSMenu *appMenu = [[menuBar itemAtIndex:0] submenu]; 201 202 self.fPreferencesMenu = (NSMenuItem*)[appMenu itemWithTag:PREFERENCES_TAG]; 203 self.fAboutMenu = (NSMenuItem*)[appMenu itemAtIndex:0]; 204 205 // If the java application has a bundle with an Info.plist file with 206 // a CFBundleDocumentTypes entry, then it is set up to handle Open Doc 207 // and Print Doc commands for these files. Therefore java AWT will 208 // cache Open Doc and Print Doc events that are sent prior to a 209 // listener being installed by the client java application. 210 NSBundle *bundle = [NSBundle mainBundle]; 211 fHandlesDocumentTypes = [bundle objectForInfoDictionaryKey:@"CFBundleDocumentTypes"] != nil || [bundle _hasEAWTOverride:@"DocumentHandler"]; 212 fHandlesURLTypes = [bundle objectForInfoDictionaryKey:@"CFBundleURLTypes"] != nil || [bundle _hasEAWTOverride:@"URLHandler"]; 213 if (fHandlesURLTypes) { 214 [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self 215 andSelector:@selector(_handleOpenURLEvent:withReplyEvent:) 216 forEventClass:kInternetEventClass 217 andEventID:kAEGetURL]; 218 } 219 220 // By HIG, Preferences are not available unless there is a handler. By default in Mac OS X, 221 // there is not a handler, but it is in the nib file for convenience. 222 removeMenuItem(self.fPreferencesMenu); 223 224 [self _updateAboutMenu:YES enabled:YES]; 225 226 // Now that the AppKit objects are known and set up, initialize the model data 227 BOOL aboutAvailable = ([self.fAboutMenu menu] != nil); 228 BOOL aboutEnabled = (aboutAvailable && [self.fAboutMenu isEnabled] && ([self.fAboutMenu target] != nil)); 229 230 BOOL prefsAvailable = ([self.fPreferencesMenu menu] != nil); 231 BOOL prefsEnabled = (prefsAvailable && [self.fPreferencesMenu isEnabled] && ([self.fPreferencesMenu target] != nil)); 232 isAppActive = NO; 233 234 JNIEnv *env = [ThreadUtilities getJNIEnv]; 235 static JNF_CLASS_CACHE(sjc_AppMenuBarHandler, "com/apple/eawt/_AppMenuBarHandler"); 236 static JNF_STATIC_MEMBER_CACHE(sjm_initMenuStates, sjc_AppMenuBarHandler, "initMenuStates", "(ZZZZ)V"); 237 JNFCallStaticVoidMethod(env, sjm_initMenuStates, aboutAvailable, aboutEnabled, prefsAvailable, prefsEnabled); 238 239 // register for the finish launching and system power off notifications by default 240 NSNotificationCenter *ctr = [NSNotificationCenter defaultCenter]; 241 Class clz = [ApplicationDelegate class]; 242 [ctr addObserver:clz selector:@selector(_willFinishLaunching) name:NSApplicationWillFinishLaunchingNotification object:nil]; 243 [ctr addObserver:clz selector:@selector(_systemWillPowerOff) name:NSWorkspaceWillPowerOffNotification object:nil]; 244 [ctr addObserver:clz selector:@selector(_appDidActivate) name:NSApplicationDidBecomeActiveNotification object:nil]; 245 [ctr addObserver:clz selector:@selector(_appDidDeactivate) name:NSApplicationDidResignActiveNotification object:nil]; 246 [ctr addObserver:clz selector:@selector(_appDidHide) name:NSApplicationDidHideNotification object:nil]; 247 [ctr addObserver:clz selector:@selector(_appDidUnhide) name:NSApplicationDidUnhideNotification object:nil]; 248 249 return self; 250 } 251 252 - (void)dealloc { 253 self.fPreferencesMenu = nil; 254 self.fAboutMenu = nil; 255 self.fDockMenu = nil; 256 self.fDefaultMenuBar = nil; 257 258 [super dealloc]; 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 - (void)applicationWillBecomeActive:(id)application { 506 isAppActive = YES; 507 } 508 509 - (void)applicationWillResignActive:(id)application { 510 isAppActive = NO; 511 } 512 513 @end 514 515 516 #pragma mark Native JNI calls 517 518 /* 519 * Class: com_apple_eawt_Application 520 * Method: nativeInitializeApplicationDelegate 521 * Signature: ()V 522 */ 523 JNIEXPORT void JNICALL Java_com_apple_eawt_Application_nativeInitializeApplicationDelegate 524 (JNIEnv *env, jclass clz) 525 { 526 JNF_COCOA_ENTER(env); 527 // Force initialization to happen on AppKit thread! 528 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 529 [ApplicationDelegate sharedDelegate]; 530 }]; 531 JNF_COCOA_EXIT(env); 532 } 533 534 /* 535 * Class: com_apple_eawt__AppEventHandler 536 * Method: nativeOpenCocoaAboutWindow 537 * Signature: ()V 538 */ 539 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeOpenCocoaAboutWindow 540 (JNIEnv *env, jclass clz) 541 { 542 JNF_COCOA_ENTER(env); 543 544 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 545 [NSApp orderFrontStandardAboutPanel:nil]; 546 }]; 547 548 JNF_COCOA_EXIT(env); 549 } 550 551 /* 552 * Class: com_apple_eawt__AppEventHandler 553 * Method: nativeReplyToAppShouldTerminate 554 * Signature: (Z)V 555 */ 556 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeReplyToAppShouldTerminate 557 (JNIEnv *env, jclass clz, jboolean doTerminate) 558 { 559 JNF_COCOA_ENTER(env); 560 561 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 562 [NSApp replyToApplicationShouldTerminate:doTerminate]; 563 }]; 564 565 JNF_COCOA_EXIT(env); 566 } 567 568 /* 569 * Class: com_apple_eawt__AppEventHandler 570 * Method: nativeRegisterForNotification 571 * Signature: (I)V 572 */ 573 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeRegisterForNotification 574 (JNIEnv *env, jclass clz, jint notificationType) 575 { 576 JNF_COCOA_ENTER(env); 577 [ThreadUtilities performOnMainThread:@selector(_registerForNotification:) 578 on:[ApplicationDelegate class] 579 withObject:[NSNumber numberWithInt:notificationType] 580 waitUntilDone:NO]; // AWT_THREADING Safe (non-blocking) 581 JNF_COCOA_EXIT(env); 582 } 583 584 /* 585 * Class: com_apple_eawt__AppDockIconHandler 586 * Method: nativeSetDockMenu 587 * Signature: (J)V 588 */ 589 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockMenu 590 (JNIEnv *env, jclass clz, jlong nsMenuPtr) 591 { 592 JNF_COCOA_ENTER(env); 593 594 NSMenu *menu = (NSMenu *)jlong_to_ptr(nsMenuPtr); 595 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 596 [ApplicationDelegate sharedDelegate].fDockMenu = menu; 597 }]; 598 599 JNF_COCOA_EXIT(env); 600 } 601 602 /* 603 * Class: com_apple_eawt__AppDockIconHandler 604 * Method: nativeSetDockIconImage 605 * Signature: (J)V 606 */ 607 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockIconImage 608 (JNIEnv *env, jclass clz, jlong nsImagePtr) 609 { 610 JNF_COCOA_ENTER(env); 611 612 NSImage *_image = (NSImage *)jlong_to_ptr(nsImagePtr); 613 [ThreadUtilities performOnMainThread:@selector(_setDockIconImage:) 614 on:[ApplicationDelegate class] 615 withObject:_image 616 waitUntilDone:NO]; 617 618 JNF_COCOA_EXIT(env); 619 } 620 621 /* 622 * Class: com_apple_eawt__AppDockIconHandler 623 * Method: nativeGetDockIconImage 624 * Signature: ()J 625 */ 626 JNIEXPORT jlong JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeGetDockIconImage 627 (JNIEnv *env, jclass clz) 628 { 629 __block NSImage *image = nil; 630 631 JNF_COCOA_ENTER(env); 632 633 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 634 image = [[ApplicationDelegate _dockIconImage] retain]; 635 }]; 636 637 JNF_COCOA_EXIT(env); 638 639 return ptr_to_jlong(image); 640 } 641 642 /* 643 * Class: com_apple_eawt__AppDockIconHandler 644 * Method: nativeSetDockIconBadge 645 * Signature: (Ljava/lang/String;)V 646 */ 647 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockIconBadge 648 (JNIEnv *env, jclass clz, jstring badge) 649 { 650 JNF_COCOA_ENTER(env); 651 652 NSString *badgeString = JNFJavaToNSString(env, badge); 653 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 654 NSDockTile *dockTile = [NSApp dockTile]; 655 [dockTile setBadgeLabel:badgeString]; 656 [dockTile display]; 657 }]; 658 659 JNF_COCOA_EXIT(env); 660 } 661 662 /* 663 * Class: com_apple_eawt__AppMiscHandlers 664 * Method: nativeRequestActivation 665 * Signature: (Z)V 666 */ 667 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeRequestActivation 668 (JNIEnv *env, jclass clz, jboolean allWindows) 669 { 670 JNF_COCOA_ENTER(env); 671 672 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 673 NSApplicationActivationOptions options = allWindows ? NSApplicationActivateAllWindows : 0; 674 options |= NSApplicationActivateIgnoringOtherApps; // without this, nothing happens! 675 [[NSRunningApplication currentApplication] activateWithOptions:options]; 676 }]; 677 678 JNF_COCOA_EXIT(env); 679 } 680 681 /* 682 * Class: com_apple_eawt__AppMiscHandlers 683 * Method: nativeRequestUserAttention 684 * Signature: (Z)V 685 */ 686 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeRequestUserAttention 687 (JNIEnv *env, jclass clz, jboolean critical) 688 { 689 JNF_COCOA_ENTER(env); 690 691 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 692 [NSApp requestUserAttention:critical ? NSCriticalRequest : NSInformationalRequest]; 693 }]; 694 695 JNF_COCOA_EXIT(env); 696 } 697 698 /* 699 * Class: com_apple_eawt__AppMiscHandlers 700 * Method: nativeOpenHelpViewer 701 * Signature: ()V 702 */ 703 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeOpenHelpViewer 704 (JNIEnv *env, jclass clz) 705 { 706 JNF_COCOA_ENTER(env); 707 708 [ThreadUtilities performOnMainThread:@selector(showHelp:) 709 on:NSApp 710 withObject:nil 711 waitUntilDone:NO]; 712 713 JNF_COCOA_EXIT(env); 714 } 715 716 /* 717 * Class: com_apple_eawt__AppMiscHandlers 718 * Method: nativeEnableSuddenTermination 719 * Signature: ()V 720 */ 721 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeEnableSuddenTermination 722 (JNIEnv *env, jclass clz) 723 { 724 JNF_COCOA_ENTER(env); 725 726 [[NSProcessInfo processInfo] enableSuddenTermination]; // Foundation thread-safe 727 728 JNF_COCOA_EXIT(env); 729 } 730 731 /* 732 * Class: com_apple_eawt__AppMiscHandlers 733 * Method: nativeDisableSuddenTermination 734 * Signature: ()V 735 */ 736 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeDisableSuddenTermination 737 (JNIEnv *env, jclass clz) 738 { 739 JNF_COCOA_ENTER(env); 740 741 [[NSProcessInfo processInfo] disableSuddenTermination]; // Foundation thread-safe 742 743 JNF_COCOA_EXIT(env); 744 } 745 746 /* 747 * Class: com_apple_eawt__AppMenuBarHandler 748 * Method: nativeSetMenuState 749 * Signature: (IZZ)V 750 */ 751 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMenuBarHandler_nativeSetMenuState 752 (JNIEnv *env, jclass clz, jint menuID, jboolean visible, jboolean enabled) 753 { 754 JNF_COCOA_ENTER(env); 755 756 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 757 ApplicationDelegate *delegate = [ApplicationDelegate sharedDelegate]; 758 switch (menuID) { 759 case com_apple_eawt__AppMenuBarHandler_MENU_ABOUT: 760 [delegate _updateAboutMenu:visible enabled:enabled]; 761 break; 762 case com_apple_eawt__AppMenuBarHandler_MENU_PREFS: 763 [delegate _updatePreferencesMenu:visible enabled:enabled]; 764 break; 765 } 766 }]; 767 768 JNF_COCOA_EXIT(env); 769 } 770 771 /* 772 * Class: com_apple_eawt__AppMenuBarHandler 773 * Method: nativeSetDefaultMenuBar 774 * Signature: (J)V 775 */ 776 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMenuBarHandler_nativeSetDefaultMenuBar 777 (JNIEnv *env, jclass clz, jlong cMenuBarPtr) 778 { 779 JNF_COCOA_ENTER(env); 780 781 CMenuBar *menu = (CMenuBar *)jlong_to_ptr(cMenuBarPtr); 782 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 783 [ApplicationDelegate sharedDelegate].fDefaultMenuBar = menu; 784 }]; 785 786 JNF_COCOA_EXIT(env); 787 }