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
226 [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self
227 andSelector:@selector(_handleOpenURLEvent:withReplyEvent:)
228 forEventClass:kInternetEventClass
229 andEventID:kAEGetURL];
230 }
231
232 // By HIG, Preferences are not available unless there is a handler. By default in Mac OS X,
233 // there is not a handler, but it is in the nib file for convenience.
234 removeMenuItem(self.fPreferencesMenu);
235
236 [self _updateAboutMenu:YES enabled:YES];
237
238 // Now that the AppKit objects are known and set up, initialize the model data
239 BOOL aboutAvailable = ([self.fAboutMenu menu] != nil);
240 BOOL aboutEnabled = (aboutAvailable && [self.fAboutMenu isEnabled] && ([self.fAboutMenu target] != nil));
241
242 BOOL prefsAvailable = ([self.fPreferencesMenu menu] != nil);
243 BOOL prefsEnabled = (prefsAvailable && [self.fPreferencesMenu isEnabled] && ([self.fPreferencesMenu target] != nil));
244
245 JNIEnv *env = [ThreadUtilities getJNIEnv];
246 static JNF_CLASS_CACHE(sjc_AppMenuBarHandler, "com/apple/eawt/_AppMenuBarHandler");
247 static JNF_STATIC_MEMBER_CACHE(sjm_initMenuStates, sjc_AppMenuBarHandler, "initMenuStates", "(ZZZZ)V");
248 JNFCallStaticVoidMethod(env, sjm_initMenuStates, aboutAvailable, aboutEnabled, prefsAvailable, prefsEnabled);
249
250 // register for the finish launching and system power off notifications by default
251 NSNotificationCenter *ctr = [NSNotificationCenter defaultCenter];
252 Class clz = [ApplicationDelegate class];
253 [ctr addObserver:clz selector:@selector(_willFinishLaunching) name:NSApplicationWillFinishLaunchingNotification object:nil];
254 [ctr addObserver:clz selector:@selector(_systemWillPowerOff) name:NSWorkspaceWillPowerOffNotification object:nil];
255 [ctr addObserver:clz selector:@selector(_appDidActivate) name:NSApplicationDidBecomeActiveNotification object:nil];
256 [ctr addObserver:clz selector:@selector(_appDidDeactivate) name:NSApplicationDidResignActiveNotification object:nil];
257 [ctr addObserver:clz selector:@selector(_appDidHide) name:NSApplicationDidHideNotification object:nil];
258 [ctr addObserver:clz selector:@selector(_appDidUnhide) name:NSApplicationDidUnhideNotification object:nil];
259
260 return self;
261 }
262
263 - (void)dealloc {
264 self.fPreferencesMenu = nil;
265 self.fAboutMenu = nil;
266 self.fDockMenu = nil;
267 self.fDefaultMenuBar = nil;
268 self.fProgressIndicator = nil;
269
270 [super dealloc];
271 }
272
273 #pragma mark Callbacks from AppKit
274
275 static JNF_CLASS_CACHE(sjc_AppEventHandler, "com/apple/eawt/_AppEventHandler");
276
277 - (void)_handleOpenURLEvent:(NSAppleEventDescriptor *)openURLEvent withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
278 AWT_ASSERT_APPKIT_THREAD;
279 if (!fHandlesURLTypes) return;
280
281 NSString *url = [[openURLEvent paramDescriptorForKeyword:keyDirectObject] stringValue];
282
283 //fprintf(stderr,"jm_handleOpenURL\n");
284 JNIEnv *env = [ThreadUtilities getJNIEnv];
285 jstring jURL = JNFNSToJavaString(env, url);
286 static JNF_STATIC_MEMBER_CACHE(jm_handleOpenURI, sjc_AppEventHandler, "handleOpenURI", "(Ljava/lang/String;)V");
287 JNFCallStaticVoidMethod(env, jm_handleOpenURI, jURL); // AWT_THREADING Safe (event)
288 (*env)->DeleteLocalRef(env, jURL);
289
290 [replyEvent insertDescriptor:[NSAppleEventDescriptor nullDescriptor] atIndex:0];
291 }
292
293 // Helper for both open file and print file methods
294 // Creates a Java list of files from a native list of files
295 - (jobject)_createFilePathArrayFrom:(NSArray *)filenames withEnv:(JNIEnv *)env {
296 static JNF_CLASS_CACHE(sjc_ArrayList, "java/util/ArrayList");
297 static JNF_CTOR_CACHE(jm_ArrayList_ctor, sjc_ArrayList, "(I)V");
298 static JNF_MEMBER_CACHE(jm_ArrayList_add, sjc_ArrayList, "add", "(Ljava/lang/Object;)Z");
299
300 jobject jFileNamesArray = JNFNewObject(env, jm_ArrayList_ctor, (jint)[filenames count]); // AWT_THREADING Safe (known object)
301 for (NSString *filename in filenames) {
302 jstring jFileName = JNFNormalizedJavaStringForPath(env, filename);
303 JNFCallVoidMethod(env, jFileNamesArray, jm_ArrayList_add, jFileName);
304 }
305
306 return jFileNamesArray;
307 }
308
309 // Open file handler
310 - (void)application:(NSApplication *)theApplication openFiles:(NSArray *)fileNames {
311 AWT_ASSERT_APPKIT_THREAD;
312 if (!fHandlesDocumentTypes) {
313 [theApplication replyToOpenOrPrint:NSApplicationDelegateReplyCancel];
314 return;
315 }
316
317 //fprintf(stderr,"jm_handleOpenFile\n");
318 JNIEnv *env = [ThreadUtilities getJNIEnv];
319
320 // if these files were opened from a Spotlight query, try to get the search text from the current AppleEvent
321 NSAppleEventDescriptor *currentEvent = [[NSAppleEventManager sharedAppleEventManager] currentAppleEvent];
322 NSString *searchString = [[currentEvent paramDescriptorForKeyword:keyAESearchText] stringValue];
323 jstring jSearchString = JNFNSToJavaString(env, searchString);
324
325 // convert the file names array
326 jobject jFileNamesArray = [self _createFilePathArrayFrom:fileNames withEnv:env];
327
328 static JNF_STATIC_MEMBER_CACHE(jm_handleOpenFiles, sjc_AppEventHandler, "handleOpenFiles", "(Ljava/util/List;Ljava/lang/String;)V");
329 JNFCallStaticVoidMethod(env, jm_handleOpenFiles, jFileNamesArray, jSearchString);
330 (*env)->DeleteLocalRef(env, jFileNamesArray);
331 (*env)->DeleteLocalRef(env, jSearchString);
332
333 [theApplication replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
334 }
335
336 // Print handler
337 - (NSApplicationPrintReply)application:(NSApplication *)application printFiles:(NSArray *)fileNames withSettings:(NSDictionary *)printSettings showPrintPanels:(BOOL)showPrintPanels {
338 AWT_ASSERT_APPKIT_THREAD;
339 if (!fHandlesDocumentTypes) return NSPrintingCancelled;
340
341 //fprintf(stderr,"jm_handlePrintFile\n");
342 JNIEnv *env = [ThreadUtilities getJNIEnv];
343 jobject jFileNamesArray = [self _createFilePathArrayFrom:fileNames withEnv:env];
344 static JNF_STATIC_MEMBER_CACHE(jm_handlePrintFile, sjc_AppEventHandler, "handlePrintFiles", "(Ljava/util/List;)V");
345 JNFCallStaticVoidMethod(env, jm_handlePrintFile, jFileNamesArray); // AWT_THREADING Safe (event)
346 (*env)->DeleteLocalRef(env, jFileNamesArray);
347
348 return NSPrintingSuccess;
349 }
350
351 // Open app handler, registered in -init
352 + (void)_notifyJava:(jint)notificationType {
353 AWT_ASSERT_APPKIT_THREAD;
354
355 //fprintf(stderr,"jm_handleOpenApplication\n");
356 JNIEnv *env = [ThreadUtilities getJNIEnv];
357 static JNF_STATIC_MEMBER_CACHE(jm_handleNativeNotification, sjc_AppEventHandler, "handleNativeNotification", "(I)V");
358 JNFCallStaticVoidMethod(env, jm_handleNativeNotification, notificationType); // AWT_THREADING Safe (event)
359 }
360
361 // About menu handler
362 - (void)_aboutMenuHandler {
363 [ApplicationDelegate _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_ABOUT];
364 }
365
366 // Preferences handler
367 - (void)_preferencesMenuHandler {
368 [ApplicationDelegate _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_PREFS];
369 }
370
371 // Open app handler, registered in -init
372 + (void)_willFinishLaunching {
373 [self _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_OPEN_APP];
374 }
375
376 // ReOpen app handler
377 - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag {
378 [ApplicationDelegate _notifyJava:com_apple_eawt__AppEventHandler_NOTIFY_REOPEN_APP];
527 [image lockFocus];
528 [view drawRect:frame];
529 [image unlockFocus];
530 [image autorelease];
531 return image;
532 }
533
534 @end
535
536
537 #pragma mark Native JNI calls
538
539 /*
540 * Class: com_apple_eawt_Application
541 * Method: nativeInitializeApplicationDelegate
542 * Signature: ()V
543 */
544 JNIEXPORT void JNICALL Java_com_apple_eawt_Application_nativeInitializeApplicationDelegate
545 (JNIEnv *env, jclass clz)
546 {
547 JNF_COCOA_ENTER(env);
548 // Force initialization to happen on AppKit thread!
549 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
550 [ApplicationDelegate sharedDelegate];
551 }];
552 JNF_COCOA_EXIT(env);
553 }
554
555 /*
556 * Class: com_apple_eawt__AppEventHandler
557 * Method: nativeOpenCocoaAboutWindow
558 * Signature: ()V
559 */
560 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeOpenCocoaAboutWindow
561 (JNIEnv *env, jclass clz)
562 {
563 JNF_COCOA_ENTER(env);
564
565 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
566 [NSApp orderFrontStandardAboutPanel:nil];
567 }];
568
569 JNF_COCOA_EXIT(env);
570 }
571
572 /*
573 * Class: com_apple_eawt__AppEventHandler
574 * Method: nativeReplyToAppShouldTerminate
575 * Signature: (Z)V
576 */
577 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeReplyToAppShouldTerminate
578 (JNIEnv *env, jclass clz, jboolean doTerminate)
579 {
580 JNF_COCOA_ENTER(env);
581
582 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
583 [NSApp replyToApplicationShouldTerminate:doTerminate];
584 }];
585
586 JNF_COCOA_EXIT(env);
587 }
588
589 /*
590 * Class: com_apple_eawt__AppEventHandler
591 * Method: nativeRegisterForNotification
592 * Signature: (I)V
593 */
594 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeRegisterForNotification
595 (JNIEnv *env, jclass clz, jint notificationType)
596 {
597 JNF_COCOA_ENTER(env);
598 [ThreadUtilities performOnMainThread:@selector(_registerForNotification:)
599 on:[ApplicationDelegate class]
600 withObject:[NSNumber numberWithInt:notificationType]
601 waitUntilDone:NO]; // AWT_THREADING Safe (non-blocking)
602 JNF_COCOA_EXIT(env);
603 }
604
605 /*
606 * Class: com_apple_eawt__AppDockIconHandler
607 * Method: nativeSetDockMenu
608 * Signature: (J)V
609 */
610 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockMenu
611 (JNIEnv *env, jclass clz, jlong nsMenuPtr)
612 {
613 JNF_COCOA_ENTER(env);
614
615 NSMenu *menu = (NSMenu *)jlong_to_ptr(nsMenuPtr);
616 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
617 [ApplicationDelegate sharedDelegate].fDockMenu = menu;
618 }];
619
620 JNF_COCOA_EXIT(env);
621 }
622
623 /*
624 * Class: com_apple_eawt__AppDockIconHandler
625 * Method: nativeSetDockIconImage
626 * Signature: (J)V
627 */
628 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockIconImage
629 (JNIEnv *env, jclass clz, jlong nsImagePtr)
630 {
631 JNF_COCOA_ENTER(env);
632
633 NSImage *_image = (NSImage *)jlong_to_ptr(nsImagePtr);
634 [ThreadUtilities performOnMainThread:@selector(_setDockIconImage:)
635 on:[ApplicationDelegate class]
636 withObject:_image
637 waitUntilDone:NO];
638
639 JNF_COCOA_EXIT(env);
640 }
641
642 /*
643 * Class: com_apple_eawt__AppDockIconHandler
644 * Method: nativeSetDockIconProgress
645 * Signature: (I)V
646 */
647 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockIconProgress
648 (JNIEnv *env, jclass clz, jint value)
649 {
650 JNF_COCOA_ENTER(env);
651
652 [ThreadUtilities performOnMainThread:@selector(_setDockIconProgress:)
653 on:[ApplicationDelegate class]
654 withObject:[NSNumber numberWithInt:value]
655 waitUntilDone:NO];
656
657 JNF_COCOA_EXIT(env);
658 }
659
660 /*
661 * Class: com_apple_eawt__AppDockIconHandler
662 * Method: nativeGetDockIconImage
663 * Signature: ()J
664 */
665 JNIEXPORT jlong JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeGetDockIconImage
666 (JNIEnv *env, jclass clz)
667 {
668 __block NSImage *image = nil;
669
670 JNF_COCOA_ENTER(env);
671
672 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
673 image = [[ApplicationDelegate _dockIconImage] retain];
674 }];
675
676 JNF_COCOA_EXIT(env);
677
678 return ptr_to_jlong(image);
679 }
680
681 /*
682 * Class: com_apple_eawt__AppDockIconHandler
683 * Method: nativeSetDockIconBadge
684 * Signature: (Ljava/lang/String;)V
685 */
686 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockIconBadge
687 (JNIEnv *env, jclass clz, jstring badge)
688 {
689 JNF_COCOA_ENTER(env);
690
691 NSString *badgeString = JNFJavaToNSString(env, badge);
692 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
693 NSDockTile *dockTile = [NSApp dockTile];
694 [dockTile setBadgeLabel:badgeString];
695 [dockTile display];
696 }];
697
698 JNF_COCOA_EXIT(env);
699 }
700
701 /*
702 * Class: com_apple_eawt__AppMiscHandlers
703 * Method: nativeRequestActivation
704 * Signature: (Z)V
705 */
706 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeRequestActivation
707 (JNIEnv *env, jclass clz, jboolean allWindows)
708 {
709 JNF_COCOA_ENTER(env);
710
711 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
712 NSApplicationActivationOptions options = allWindows ? NSApplicationActivateAllWindows : 0;
713 options |= NSApplicationActivateIgnoringOtherApps; // without this, nothing happens!
714 [[NSRunningApplication currentApplication] activateWithOptions:options];
715 }];
716
717 JNF_COCOA_EXIT(env);
718 }
719
720 /*
721 * Class: com_apple_eawt__AppMiscHandlers
722 * Method: nativeRequestUserAttention
723 * Signature: (Z)V
724 */
725 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeRequestUserAttention
726 (JNIEnv *env, jclass clz, jboolean critical)
727 {
728 JNF_COCOA_ENTER(env);
729
730 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
731 [NSApp requestUserAttention:critical ? NSCriticalRequest : NSInformationalRequest];
732 }];
733
734 JNF_COCOA_EXIT(env);
735 }
736
737 /*
738 * Class: com_apple_eawt__AppMiscHandlers
739 * Method: nativeOpenHelpViewer
740 * Signature: ()V
741 */
742 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeOpenHelpViewer
743 (JNIEnv *env, jclass clz)
744 {
745 JNF_COCOA_ENTER(env);
746
747 [ThreadUtilities performOnMainThread:@selector(showHelp:)
748 on:NSApp
749 withObject:nil
750 waitUntilDone:NO];
751
752 JNF_COCOA_EXIT(env);
753 }
754
755 /*
756 * Class: com_apple_eawt__AppMiscHandlers
757 * Method: nativeEnableSuddenTermination
758 * Signature: ()V
759 */
760 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeEnableSuddenTermination
761 (JNIEnv *env, jclass clz)
762 {
763 JNF_COCOA_ENTER(env);
764
765 [[NSProcessInfo processInfo] enableSuddenTermination]; // Foundation thread-safe
766
767 JNF_COCOA_EXIT(env);
768 }
769
770 /*
771 * Class: com_apple_eawt__AppMiscHandlers
772 * Method: nativeDisableSuddenTermination
773 * Signature: ()V
774 */
775 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeDisableSuddenTermination
776 (JNIEnv *env, jclass clz)
777 {
778 JNF_COCOA_ENTER(env);
779
780 [[NSProcessInfo processInfo] disableSuddenTermination]; // Foundation thread-safe
781
782 JNF_COCOA_EXIT(env);
783 }
784
785 /*
786 * Class: com_apple_eawt__AppMenuBarHandler
787 * Method: nativeSetMenuState
788 * Signature: (IZZ)V
789 */
790 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMenuBarHandler_nativeSetMenuState
791 (JNIEnv *env, jclass clz, jint menuID, jboolean visible, jboolean enabled)
792 {
793 JNF_COCOA_ENTER(env);
794
795 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
796 ApplicationDelegate *delegate = [ApplicationDelegate sharedDelegate];
797 switch (menuID) {
798 case com_apple_eawt__AppMenuBarHandler_MENU_ABOUT:
799 [delegate _updateAboutMenu:visible enabled:enabled];
800 break;
801 case com_apple_eawt__AppMenuBarHandler_MENU_PREFS:
802 [delegate _updatePreferencesMenu:visible enabled:enabled];
803 break;
804 }
805 }];
806
807 JNF_COCOA_EXIT(env);
808 }
809
810 /*
811 * Class: com_apple_eawt__AppMenuBarHandler
812 * Method: nativeSetDefaultMenuBar
813 * Signature: (J)V
814 */
815 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMenuBarHandler_nativeSetDefaultMenuBar
816 (JNIEnv *env, jclass clz, jlong cMenuBarPtr)
817 {
818 JNF_COCOA_ENTER(env);
819
820 CMenuBar *menu = (CMenuBar *)jlong_to_ptr(cMenuBarPtr);
821 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
822 [ApplicationDelegate sharedDelegate].fDefaultMenuBar = menu;
823 }];
824
825 JNF_COCOA_EXIT(env);
826 }
|
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
46 static void addMenuItem(NSMenuItem* menuItem, NSInteger index) {
47 AWT_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
56 static void removeMenuItem(NSMenuItem* menuItem) {
57 AWT_ASSERT_APPKIT_THREAD;
58
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
276 static 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 {
284 AWT_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 {
327 AWT_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 {
357 AWT_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 {
375 AWT_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];
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 */
568 JNIEXPORT void JNICALL Java_com_apple_eawt_Application_nativeInitializeApplicationDelegate
569 (JNIEnv *env, jclass clz)
570 {
571 JNI_COCOA_ENTER(env);
572 // Force initialization to happen on AppKit thread!
573 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
574 [ApplicationDelegate sharedDelegate];
575 }];
576 JNI_COCOA_EXIT(env);
577 }
578
579 /*
580 * Class: com_apple_eawt__AppEventHandler
581 * Method: nativeOpenCocoaAboutWindow
582 * Signature: ()V
583 */
584 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeOpenCocoaAboutWindow
585 (JNIEnv *env, jclass clz)
586 {
587 JNI_COCOA_ENTER(env);
588
589 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
590 [NSApp orderFrontStandardAboutPanel:nil];
591 }];
592
593 JNI_COCOA_EXIT(env);
594 }
595
596 /*
597 * Class: com_apple_eawt__AppEventHandler
598 * Method: nativeReplyToAppShouldTerminate
599 * Signature: (Z)V
600 */
601 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeReplyToAppShouldTerminate
602 (JNIEnv *env, jclass clz, jboolean doTerminate)
603 {
604 JNI_COCOA_ENTER(env);
605
606 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
607 [NSApp replyToApplicationShouldTerminate:doTerminate];
608 }];
609
610 JNI_COCOA_EXIT(env);
611 }
612
613 /*
614 * Class: com_apple_eawt__AppEventHandler
615 * Method: nativeRegisterForNotification
616 * Signature: (I)V
617 */
618 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppEventHandler_nativeRegisterForNotification
619 (JNIEnv *env, jclass clz, jint notificationType)
620 {
621 JNI_COCOA_ENTER(env);
622 [ThreadUtilities performOnMainThread:@selector(_registerForNotification:)
623 on:[ApplicationDelegate class]
624 withObject:[NSNumber numberWithInt:notificationType]
625 waitUntilDone:NO];
626 JNI_COCOA_EXIT(env);
627 }
628
629 /*
630 * Class: com_apple_eawt__AppDockIconHandler
631 * Method: nativeSetDockMenu
632 * Signature: (J)V
633 */
634 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockMenu
635 (JNIEnv *env, jclass clz, jlong nsMenuPtr)
636 {
637 JNI_COCOA_ENTER(env);
638
639 NSMenu *menu = (NSMenu *)jlong_to_ptr(nsMenuPtr);
640 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
641 [ApplicationDelegate sharedDelegate].fDockMenu = menu;
642 }];
643
644 JNI_COCOA_EXIT(env);
645 }
646
647 /*
648 * Class: com_apple_eawt__AppDockIconHandler
649 * Method: nativeSetDockIconImage
650 * Signature: (J)V
651 */
652 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockIconImage
653 (JNIEnv *env, jclass clz, jlong nsImagePtr)
654 {
655 JNI_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
663 JNI_COCOA_EXIT(env);
664 }
665
666 /*
667 * Class: com_apple_eawt__AppDockIconHandler
668 * Method: nativeSetDockIconProgress
669 * Signature: (I)V
670 */
671 JNIEXPORT 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 */
689 JNIEXPORT jlong JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeGetDockIconImage
690 (JNIEnv *env, jclass clz)
691 {
692 __block NSImage *image = nil;
693
694 JNI_COCOA_ENTER(env);
695
696 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
697 image = [[ApplicationDelegate _dockIconImage] retain];
698 }];
699
700 JNI_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 */
710 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppDockIconHandler_nativeSetDockIconBadge
711 (JNIEnv *env, jclass clz, jstring badge)
712 {
713 JNI_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
722 JNI_COCOA_EXIT(env);
723 }
724
725 /*
726 * Class: com_apple_eawt__AppMiscHandlers
727 * Method: nativeRequestActivation
728 * Signature: (Z)V
729 */
730 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeRequestActivation
731 (JNIEnv *env, jclass clz, jboolean allWindows)
732 {
733 JNI_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
741 JNI_COCOA_EXIT(env);
742 }
743
744 /*
745 * Class: com_apple_eawt__AppMiscHandlers
746 * Method: nativeRequestUserAttention
747 * Signature: (Z)V
748 */
749 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeRequestUserAttention
750 (JNIEnv *env, jclass clz, jboolean critical)
751 {
752 JNI_COCOA_ENTER(env);
753
754 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
755 [NSApp requestUserAttention:critical ? NSCriticalRequest : NSInformationalRequest];
756 }];
757
758 JNI_COCOA_EXIT(env);
759 }
760
761 /*
762 * Class: com_apple_eawt__AppMiscHandlers
763 * Method: nativeOpenHelpViewer
764 * Signature: ()V
765 */
766 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeOpenHelpViewer
767 (JNIEnv *env, jclass clz)
768 {
769 JNI_COCOA_ENTER(env);
770
771 [ThreadUtilities performOnMainThread:@selector(showHelp:)
772 on:NSApp
773 withObject:nil
774 waitUntilDone:NO];
775
776 JNI_COCOA_EXIT(env);
777 }
778
779 /*
780 * Class: com_apple_eawt__AppMiscHandlers
781 * Method: nativeEnableSuddenTermination
782 * Signature: ()V
783 */
784 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeEnableSuddenTermination
785 (JNIEnv *env, jclass clz)
786 {
787 JNI_COCOA_ENTER(env);
788
789 [[NSProcessInfo processInfo] enableSuddenTermination]; // Foundation thread-safe
790
791 JNI_COCOA_EXIT(env);
792 }
793
794 /*
795 * Class: com_apple_eawt__AppMiscHandlers
796 * Method: nativeDisableSuddenTermination
797 * Signature: ()V
798 */
799 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMiscHandlers_nativeDisableSuddenTermination
800 (JNIEnv *env, jclass clz)
801 {
802 JNI_COCOA_ENTER(env);
803
804 [[NSProcessInfo processInfo] disableSuddenTermination]; // Foundation thread-safe
805
806 JNI_COCOA_EXIT(env);
807 }
808
809 /*
810 * Class: com_apple_eawt__AppMenuBarHandler
811 * Method: nativeSetMenuState
812 * Signature: (IZZ)V
813 */
814 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMenuBarHandler_nativeSetMenuState
815 (JNIEnv *env, jclass clz, jint menuID, jboolean visible, jboolean enabled)
816 {
817 JNI_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
831 JNI_COCOA_EXIT(env);
832 }
833
834 /*
835 * Class: com_apple_eawt__AppMenuBarHandler
836 * Method: nativeSetDefaultMenuBar
837 * Signature: (J)V
838 */
839 JNIEXPORT void JNICALL Java_com_apple_eawt__1AppMenuBarHandler_nativeSetDefaultMenuBar
840 (JNIEnv *env, jclass clz, jlong cMenuBarPtr)
841 {
842 JNI_COCOA_ENTER(env);
843
844 CMenuBar *menu = (CMenuBar *)jlong_to_ptr(cMenuBarPtr);
845 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
846 [ApplicationDelegate sharedDelegate].fDefaultMenuBar = menu;
847 }];
848
849 JNI_COCOA_EXIT(env);
850 }
|