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