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 <dlfcn.h> 27 #import <pthread.h> 28 #import <objc/runtime.h> 29 #import <Cocoa/Cocoa.h> 30 #import <Security/AuthSession.h> 31 #import <JavaNativeFoundation/JavaNativeFoundation.h> 32 #import <JavaRuntimeSupport/JavaRuntimeSupport.h> 33 34 #include "jni_util.h" 35 #import "CMenuBar.h" 36 #import "InitIDs.h" 37 #import "LWCToolkit.h" 38 #import "ThreadUtilities.h" 39 #import "AWT_debug.h" 40 #import "CSystemColors.h" 41 #import "NSApplicationAWT.h" 42 #import "PropertiesUtilities.h" 43 #import "ApplicationDelegate.h" 44 45 #import "sun_lwawt_macosx_LWCToolkit.h" 46 47 #import "sizecalc.h" 48 49 int gNumberOfButtons; 50 jint* gButtonDownMasks; 51 52 // Indicates that the app has been started with -XstartOnFirstThread 53 // (directly or via WebStart settings), and AWT should not run its 54 // own event loop in this mode. Even if a loop isn't running yet, 55 // we expect an embedder (e.g. SWT) to start it some time later. 56 static BOOL forceEmbeddedMode = NO; 57 58 // Indicates if awt toolkit is embedded into another UI toolkit 59 static BOOL isEmbedded = NO; 60 61 // This is the data necessary to have JNI_OnLoad wait for AppKit to start. 62 static BOOL sAppKitStarted = NO; 63 static pthread_mutex_t sAppKitStarted_mutex = PTHREAD_MUTEX_INITIALIZER; 64 static pthread_cond_t sAppKitStarted_cv = PTHREAD_COND_INITIALIZER; 65 66 @implementation AWTToolkit 67 68 static long eventCount; 69 70 + (long) getEventCount{ 71 return eventCount; 72 } 73 74 + (void) eventCountPlusPlus{ 75 eventCount++; 76 } 77 78 @end 79 80 81 @interface AWTRunLoopObject : NSObject { 82 BOOL _shouldEndRunLoop; 83 } 84 @end 85 86 @implementation AWTRunLoopObject 87 88 - (id) init { 89 self = [super init]; 90 if (self != nil) { 91 _shouldEndRunLoop = NO; 92 } 93 return self; 94 } 95 96 - (BOOL) shouldEndRunLoop { 97 return _shouldEndRunLoop; 98 } 99 100 - (void) endRunLoop { 101 _shouldEndRunLoop = YES; 102 } 103 104 @end 105 106 @interface JavaRunnable : NSObject { } 107 @property jobject runnable; 108 - (id)initWithRunnable:(jobject)gRunnable; 109 - (void)perform; 110 @end 111 112 @implementation JavaRunnable 113 @synthesize runnable = _runnable; 114 115 - (id)initWithRunnable:(jobject)gRunnable { 116 if (self = [super init]) { 117 self.runnable = gRunnable; 118 } 119 return self; 120 } 121 122 - (void)dealloc { 123 JNIEnv *env = [ThreadUtilities getJNIEnv]; 124 if (self.runnable) { 125 (*env)->DeleteGlobalRef(env, self.runnable); 126 } 127 [super dealloc]; 128 } 129 130 - (void)perform { 131 JNIEnv* env = [ThreadUtilities getJNIEnv]; 132 static JNF_CLASS_CACHE(sjc_Runnable, "java/lang/Runnable"); 133 static JNF_MEMBER_CACHE(jm_Runnable_run, sjc_Runnable, "run", "()V"); 134 JNFCallVoidMethod(env, self.runnable, jm_Runnable_run); 135 [self release]; 136 } 137 @end 138 139 void setBusy(BOOL busy) { 140 AWT_ASSERT_APPKIT_THREAD; 141 142 JNIEnv *env = [ThreadUtilities getJNIEnv]; 143 static JNF_CLASS_CACHE(jc_AWTAutoShutdown, "sun/awt/AWTAutoShutdown"); 144 145 if (busy) { 146 static JNF_STATIC_MEMBER_CACHE(jm_notifyBusyMethod, jc_AWTAutoShutdown, "notifyToolkitThreadBusy", "()V"); 147 JNFCallStaticVoidMethod(env, jm_notifyBusyMethod); 148 } else { 149 static JNF_STATIC_MEMBER_CACHE(jm_notifyFreeMethod, jc_AWTAutoShutdown, "notifyToolkitThreadFree", "()V"); 150 JNFCallStaticVoidMethod(env, jm_notifyFreeMethod); 151 } 152 } 153 154 static void setUpAWTAppKit(BOOL installObservers) 155 { 156 if (installObservers) { 157 AWT_STARTUP_LOG(@"Setting up busy observers"); 158 159 // Add CFRunLoopObservers to call into AWT so that AWT knows that the 160 // AWT thread (which is the AppKit main thread) is alive. This way AWT 161 // will not automatically shutdown. 162 CFRunLoopObserverRef busyObserver = CFRunLoopObserverCreateWithHandler( 163 NULL, // CFAllocator 164 kCFRunLoopAfterWaiting, // CFOptionFlags 165 true, // repeats 166 NSIntegerMax, // order 167 ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { 168 setBusy(YES); 169 }); 170 171 CFRunLoopObserverRef notBusyObserver = CFRunLoopObserverCreateWithHandler( 172 NULL, // CFAllocator 173 kCFRunLoopBeforeWaiting, // CFOptionFlags 174 true, // repeats 175 NSIntegerMin, // order 176 ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) { 177 setBusy(NO); 178 }); 179 180 CFRunLoopRef runLoop = [[NSRunLoop currentRunLoop] getCFRunLoop]; 181 CFRunLoopAddObserver(runLoop, busyObserver, kCFRunLoopDefaultMode); 182 CFRunLoopAddObserver(runLoop, notBusyObserver, kCFRunLoopDefaultMode); 183 184 CFRelease(busyObserver); 185 CFRelease(notBusyObserver); 186 187 setBusy(YES); 188 } 189 190 JNIEnv* env = [ThreadUtilities getJNIEnv]; 191 static JNF_CLASS_CACHE(jc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit"); 192 static JNF_STATIC_MEMBER_CACHE(jsm_installToolkitThreadInJava, jc_LWCToolkit, "installToolkitThreadInJava", "()V"); 193 JNFCallStaticVoidMethod(env, jsm_installToolkitThreadInJava); 194 } 195 196 BOOL isSWTInWebStart(JNIEnv* env) { 197 NSString *swtWebStart = [PropertiesUtilities javaSystemPropertyForKey:@"com.apple.javaws.usingSWT" withEnv:env]; 198 return [@"true" isCaseInsensitiveLike:swtWebStart]; 199 } 200 201 static void AWT_NSUncaughtExceptionHandler(NSException *exception) { 202 NSLog(@"Apple AWT Internal Exception: %@", [exception description]); 203 } 204 205 @interface AWTStarter : NSObject 206 + (void)start:(BOOL)headless; 207 + (void)starter:(BOOL)onMainThread headless:(BOOL)headless; 208 + (void)appKitIsRunning:(id)arg; 209 @end 210 211 @implementation AWTStarter 212 213 + (BOOL) isConnectedToWindowServer { 214 SecuritySessionId session_id; 215 SessionAttributeBits session_info; 216 OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info); 217 if (status != noErr) return NO; 218 if (!(session_info & sessionHasGraphicAccess)) return NO; 219 return YES; 220 } 221 222 + (BOOL) markAppAsDaemon { 223 id jrsAppKitAWTClass = objc_getClass("JRSAppKitAWT"); 224 SEL markAppSel = @selector(markAppIsDaemon); 225 if (![jrsAppKitAWTClass respondsToSelector:markAppSel]) return NO; 226 return [jrsAppKitAWTClass performSelector:markAppSel] ? YES : NO; 227 } 228 229 + (void)appKitIsRunning:(id)arg { 230 AWT_ASSERT_APPKIT_THREAD; 231 AWT_STARTUP_LOG(@"About to message AppKit started"); 232 233 // Signal that AppKit has started (or is already running). 234 pthread_mutex_lock(&sAppKitStarted_mutex); 235 sAppKitStarted = YES; 236 pthread_cond_signal(&sAppKitStarted_cv); 237 pthread_mutex_unlock(&sAppKitStarted_mutex); 238 239 AWT_STARTUP_LOG(@"Finished messaging AppKit started"); 240 } 241 242 + (void)start:(BOOL)headless 243 { 244 // onMainThread is NOT the same at SWT mode! 245 // If the JVM was started on the first thread for SWT, but the SWT loads the AWT on a secondary thread, 246 // onMainThread here will be false but SWT mode will be true. If we are currently on the main thread, we don't 247 // need to throw AWT startup over to another thread. 248 BOOL onMainThread = [NSThread isMainThread]; 249 250 NSString* msg = [NSString stringWithFormat:@"+[AWTStarter start headless:%d] { onMainThread:%d }", headless, onMainThread]; 251 AWT_STARTUP_LOG(msg); 252 253 if (!headless) 254 { 255 // Listen for the NSApp to start. This indicates that JNI_OnLoad can proceed. 256 // It must wait because there is a chance that another java thread will grab 257 // the AppKit lock before the +[NSApplication sharedApplication] returns. 258 // See <rdar://problem/3492666> for an example. 259 [[NSNotificationCenter defaultCenter] addObserver:[AWTStarter class] 260 selector:@selector(appKitIsRunning:) 261 name:NSApplicationDidFinishLaunchingNotification 262 object:nil]; 263 264 AWT_STARTUP_LOG(@"+[AWTStarter start:::]: registered NSApplicationDidFinishLaunchingNotification"); 265 } 266 267 [ThreadUtilities performOnMainThreadWaiting:NO block:^() { 268 [AWTStarter starter:onMainThread headless:headless]; 269 }]; 270 271 272 if (!headless && !onMainThread) { 273 274 AWT_STARTUP_LOG(@"about to wait on AppKit startup mutex"); 275 276 // Wait here for AppKit to have started (or for AWT to have been loaded into 277 // an already running NSApplication). 278 pthread_mutex_lock(&sAppKitStarted_mutex); 279 while (sAppKitStarted == NO) { 280 pthread_cond_wait(&sAppKitStarted_cv, &sAppKitStarted_mutex); 281 } 282 pthread_mutex_unlock(&sAppKitStarted_mutex); 283 284 // AWT gets here AFTER +[AWTStarter appKitIsRunning:] is called. 285 AWT_STARTUP_LOG(@"got out of the AppKit startup mutex"); 286 } 287 288 if (!headless) { 289 // Don't set the delegate until the NSApplication has been created and 290 // its finishLaunching has initialized it. 291 // ApplicationDelegate is the support code for com.apple.eawt. 292 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ 293 id<NSApplicationDelegate> delegate = [ApplicationDelegate sharedDelegate]; 294 if (delegate != nil) { 295 OSXAPP_SetApplicationDelegate(delegate); 296 } 297 }]; 298 } 299 } 300 301 + (void)starter:(BOOL)wasOnMainThread headless:(BOOL)headless { 302 NSAutoreleasePool *pool = [NSAutoreleasePool new]; 303 // Add the exception handler of last resort 304 NSSetUncaughtExceptionHandler(AWT_NSUncaughtExceptionHandler); 305 306 // Headless mode trumps either ordinary AWT or SWT-in-AWT mode. Declare us a daemon and return. 307 if (headless) { 308 // Note that we don't install run loop observers in headless mode 309 // because we don't need them (see 7174704) 310 if (!forceEmbeddedMode) { 311 setUpAWTAppKit(false); 312 } 313 [AWTStarter markAppAsDaemon]; 314 return; 315 } 316 317 if (forceEmbeddedMode) { 318 AWT_STARTUP_LOG(@"in SWT or SWT/WebStart mode"); 319 320 // Init a default NSApplication instance instead of the NSApplicationAWT. 321 // Note that [NSApp isRunning] will return YES after that, though 322 // this behavior isn't specified anywhere. We rely on that. 323 NSApplicationLoad(); 324 } 325 326 // This will create a NSApplicationAWT for standalone AWT programs, unless there is 327 // already a NSApplication instance. If there is already a NSApplication instance, 328 // and -[NSApplication isRunning] returns YES, AWT is embedded inside another 329 // AppKit Application. 330 NSApplication *app = [NSApplicationAWT sharedApplication]; 331 isEmbedded = ![NSApp isKindOfClass:[NSApplicationAWT class]]; 332 333 if (!isEmbedded) { 334 // Install run loop observers and set the AppKit Java thread name 335 setUpAWTAppKit(true); 336 } 337 338 // AWT gets to this point BEFORE NSApplicationDidFinishLaunchingNotification is sent. 339 if (![app isRunning]) { 340 AWT_STARTUP_LOG(@"+[AWTStarter startAWT]: ![app isRunning]"); 341 // This is where the AWT AppKit thread parks itself to process events. 342 [NSApplicationAWT runAWTLoopWithApp: app]; 343 } else { 344 // We're either embedded, or showing a splash screen 345 if (isEmbedded) { 346 AWT_STARTUP_LOG(@"running embedded"); 347 348 // We don't track if the runloop is busy, so set it free to let AWT finish when it needs 349 setBusy(NO); 350 } else { 351 AWT_STARTUP_LOG(@"running after showing a splash screen"); 352 } 353 354 // Signal so that JNI_OnLoad can proceed. 355 if (!wasOnMainThread) [AWTStarter appKitIsRunning:nil]; 356 357 // Proceed to exit this call as there is no reason to run the NSApplication event loop. 358 } 359 360 [pool drain]; 361 } 362 363 @end 364 365 /* 366 * Class: sun_lwawt_macosx_LWCToolkit 367 * Method: nativeSyncQueue 368 * Signature: (J)Z 369 */ 370 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_nativeSyncQueue 371 (JNIEnv *env, jobject self, jlong timeout) 372 { 373 int currentEventNum = [AWTToolkit getEventCount]; 374 375 NSApplication* sharedApp = [NSApplication sharedApplication]; 376 if ([sharedApp isKindOfClass:[NSApplicationAWT class]]) { 377 NSApplicationAWT* theApp = (NSApplicationAWT*)sharedApp; 378 [theApp postDummyEvent]; 379 [theApp waitForDummyEvent]; 380 } else { 381 // could happen if we are embedded inside SWT application, 382 // in this case just spin a single empty block through 383 // the event loop to give it a chance to process pending events 384 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){}]; 385 } 386 387 if (([AWTToolkit getEventCount] - currentEventNum) != 0) { 388 return JNI_TRUE; 389 } 390 391 return JNI_FALSE; 392 } 393 394 /* 395 * Class: sun_lwawt_macosx_LWCToolkit 396 * Method: flushNativeSelectors 397 * Signature: ()J 398 */ 399 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_flushNativeSelectors 400 (JNIEnv *env, jclass clz) 401 { 402 JNF_COCOA_ENTER(env); 403 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){}]; 404 JNF_COCOA_EXIT(env); 405 } 406 407 /* 408 * Class: sun_lwawt_macosx_LWCToolkit 409 * Method: beep 410 * Signature: ()V 411 */ 412 JNIEXPORT void JNICALL 413 Java_sun_lwawt_macosx_LWCToolkit_beep 414 (JNIEnv *env, jobject self) 415 { 416 NSBeep(); // produces both sound and visual flash, if configured in System Preferences 417 } 418 419 static UInt32 RGB(NSColor *c) { 420 c = [c colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; 421 if (c == nil) 422 { 423 return -1; // opaque white 424 } 425 426 CGFloat r, g, b, a; 427 [c getRed:&r green:&g blue:&b alpha:&a]; 428 429 UInt32 ir = (UInt32) (r*255+0.5), 430 ig = (UInt32) (g*255+0.5), 431 ib = (UInt32) (b*255+0.5), 432 ia = (UInt32) (a*255+0.5); 433 434 // NSLog(@"%@ %d, %d, %d", c, ir, ig, ib); 435 436 return ((ia & 0xFF) << 24) | ((ir & 0xFF) << 16) | ((ig & 0xFF) << 8) | ((ib & 0xFF) << 0); 437 } 438 439 BOOL doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) { 440 jint len = (*env)->GetArrayLength(env, jColors); 441 442 UInt32 colorsArray[len]; 443 UInt32 *colors = colorsArray; 444 445 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ 446 NSUInteger i; 447 for (i = 0; i < len; i++) { 448 colors[i] = RGB([CSystemColors getColor:i useAppleColor:useAppleColors]); 449 } 450 }]; 451 452 jint *_colors = (*env)->GetPrimitiveArrayCritical(env, jColors, 0); 453 if (_colors == NULL) { 454 return NO; 455 } 456 memcpy(_colors, colors, len * sizeof(UInt32)); 457 (*env)->ReleasePrimitiveArrayCritical(env, jColors, _colors, 0); 458 return YES; 459 } 460 461 /** 462 * Class: sun_lwawt_macosx_LWCToolkit 463 * Method: loadNativeColors 464 * Signature: ([I[I)V 465 */ 466 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_loadNativeColors 467 (JNIEnv *env, jobject peer, jintArray jSystemColors, jintArray jAppleColors) 468 { 469 JNF_COCOA_ENTER(env); 470 if (doLoadNativeColors(env, jSystemColors, NO)) { 471 doLoadNativeColors(env, jAppleColors, YES); 472 } 473 JNF_COCOA_EXIT(env); 474 } 475 476 /* 477 * Class: sun_lwawt_macosx_LWCToolkit 478 * Method: createAWTRunLoopMediator 479 * Signature: ()J 480 */ 481 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_LWCToolkit_createAWTRunLoopMediator 482 (JNIEnv *env, jclass clz) 483 { 484 AWT_ASSERT_APPKIT_THREAD; 485 486 jlong result; 487 488 JNF_COCOA_ENTER(env); 489 // We double retain because this object is owned by both main thread and "other" thread 490 // We release in both doAWTRunLoop and stopAWTRunLoop 491 result = ptr_to_jlong([[[AWTRunLoopObject alloc] init] retain]); 492 JNF_COCOA_EXIT(env); 493 494 return result; 495 } 496 497 /* 498 * Class: sun_lwawt_macosx_LWCToolkit 499 * Method: doAWTRunLoopImpl 500 * Signature: (JZZ)V 501 */ 502 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoopImpl 503 (JNIEnv *env, jclass clz, jlong mediator, jboolean processEvents, jboolean inAWT) 504 { 505 AWT_ASSERT_APPKIT_THREAD; 506 JNF_COCOA_ENTER(env); 507 508 AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator); 509 510 if (mediatorObject == nil) return; 511 512 // Don't use acceptInputForMode because that doesn't setup autorelease pools properly 513 BOOL isRunning = true; 514 while (![mediatorObject shouldEndRunLoop] && isRunning) { 515 isRunning = [[NSRunLoop currentRunLoop] runMode:(inAWT ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode) 516 beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]]; 517 if (processEvents) { 518 //We do not spin a runloop here as date is nil, so does not matter which mode to use 519 NSEvent *event; 520 if ((event = [NSApp nextEventMatchingMask:NSAnyEventMask 521 untilDate:nil 522 inMode:NSDefaultRunLoopMode 523 dequeue:YES]) != nil) { 524 [NSApp sendEvent:event]; 525 } 526 527 } 528 } 529 [mediatorObject release]; 530 JNF_COCOA_EXIT(env); 531 } 532 533 /* 534 * Class: sun_lwawt_macosx_LWCToolkit 535 * Method: stopAWTRunLoop 536 * Signature: (J)V 537 */ 538 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_stopAWTRunLoop 539 (JNIEnv *env, jclass clz, jlong mediator) 540 { 541 JNF_COCOA_ENTER(env); 542 543 AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator); 544 545 [ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO]; 546 547 [mediatorObject release]; 548 549 JNF_COCOA_EXIT(env); 550 } 551 552 /* 553 * Class: sun_lwawt_macosx_LWCToolkit 554 * Method: performOnMainThreadAfterDelay 555 * Signature: (Ljava/lang/Runnable;J)V 556 */ 557 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_performOnMainThreadAfterDelay 558 (JNIEnv *env, jclass clz, jobject runnable, jlong delay) 559 { 560 JNF_COCOA_ENTER(env); 561 jobject gRunnable = (*env)->NewGlobalRef(env, runnable); 562 CHECK_NULL(gRunnable); 563 [ThreadUtilities performOnMainThreadWaiting:NO block:^() { 564 JavaRunnable* performer = [[JavaRunnable alloc] initWithRunnable:gRunnable]; 565 [performer performSelector:@selector(perform) withObject:nil afterDelay:(delay/1000.0)]; 566 }]; 567 JNF_COCOA_EXIT(env); 568 } 569 570 571 /* 572 * Class: sun_lwawt_macosx_LWCToolkit 573 * Method: isCapsLockOn 574 * Signature: ()Z 575 */ 576 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isCapsLockOn 577 (JNIEnv *env, jobject self) 578 { 579 __block jboolean isOn = JNI_FALSE; 580 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ 581 NSUInteger modifiers = [NSEvent modifierFlags]; 582 isOn = (modifiers & NSAlphaShiftKeyMask) != 0; 583 }]; 584 585 return isOn; 586 } 587 588 /* 589 * Class: sun_lwawt_macosx_LWCToolkit 590 * Method: isApplicationActive 591 * Signature: ()Z 592 */ 593 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isApplicationActive 594 (JNIEnv *env, jclass clazz) 595 { 596 __block jboolean active = JNI_FALSE; 597 598 JNF_COCOA_ENTER(env); 599 600 [ThreadUtilities performOnMainThreadWaiting:YES block:^() { 601 active = (jboolean)[NSRunningApplication currentApplication].active; 602 }]; 603 604 JNF_COCOA_EXIT(env); 605 606 return active; 607 } 608 609 /* 610 * Class: sun_lwawt_macosx_LWCToolkit 611 * Method: activateApplicationIgnoringOtherApps 612 * Signature: ()V 613 */ 614 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_activateApplicationIgnoringOtherApps 615 (JNIEnv *env, jclass clazz) 616 { 617 JNF_COCOA_ENTER(env); 618 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 619 if(![NSApp isActive]){ 620 [NSApp activateIgnoringOtherApps:YES]; 621 } 622 }]; 623 JNF_COCOA_EXIT(env); 624 } 625 626 627 /* 628 * Class: sun_awt_SunToolkit 629 * Method: closeSplashScreen 630 * Signature: ()V 631 */ 632 JNIEXPORT void JNICALL 633 Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv *env, jclass cls) 634 { 635 void *hSplashLib = dlopen(0, RTLD_LAZY); 636 if (!hSplashLib) return; 637 638 void (*splashClose)() = dlsym(hSplashLib, "SplashClose"); 639 if (splashClose) { 640 splashClose(); 641 } 642 dlclose(hSplashLib); 643 } 644 645 646 // TODO: definitely doesn't belong here (copied from fontpath.c in the 647 // solaris tree)... 648 649 JNIEXPORT jstring JNICALL 650 Java_sun_font_FontManager_getFontPath 651 (JNIEnv *env, jclass obj, jboolean noType1) 652 { 653 return JNFNSToJavaString(env, @"/Library/Fonts"); 654 } 655 656 // This isn't yet used on unix, the implementation is added since shared 657 // code calls this method in preparation for future use. 658 JNIEXPORT void JNICALL 659 Java_sun_font_FontManager_populateFontFileNameMap 660 (JNIEnv *env, jclass obj, jobject fontToFileMap, jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale) 661 { 662 663 } 664 665 /* 666 * Class: sun_lwawt_macosx_LWCToolkit 667 * Method: initIDs 668 * Signature: ()V 669 */ 670 JNIEXPORT void JNICALL 671 Java_sun_lwawt_macosx_LWCToolkit_initIDs 672 (JNIEnv *env, jclass klass) { 673 674 JNF_COCOA_ENTER(env) 675 676 gNumberOfButtons = sun_lwawt_macosx_LWCToolkit_BUTTONS; 677 678 jclass inputEventClazz = (*env)->FindClass(env, "java/awt/event/InputEvent"); 679 CHECK_NULL(inputEventClazz); 680 jmethodID getButtonDownMasksID = (*env)->GetStaticMethodID(env, inputEventClazz, "getButtonDownMasks", "()[I"); 681 CHECK_NULL(getButtonDownMasksID); 682 jintArray obj = (jintArray)(*env)->CallStaticObjectMethod(env, inputEventClazz, getButtonDownMasksID); 683 jint * tmp = (*env)->GetIntArrayElements(env, obj, JNI_FALSE); 684 CHECK_NULL(tmp); 685 686 gButtonDownMasks = (jint*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(jint), gNumberOfButtons); 687 if (gButtonDownMasks == NULL) { 688 gNumberOfButtons = 0; 689 (*env)->ReleaseIntArrayElements(env, obj, tmp, JNI_ABORT); 690 JNU_ThrowOutOfMemoryError(env, NULL); 691 return; 692 } 693 694 int i; 695 for (i = 0; i < gNumberOfButtons; i++) { 696 gButtonDownMasks[i] = tmp[i]; 697 } 698 699 (*env)->ReleaseIntArrayElements(env, obj, tmp, 0); 700 (*env)->DeleteLocalRef(env, obj); 701 702 JNF_COCOA_EXIT(env) 703 } 704 705 /* 706 * Class: sun_lwawt_macosx_LWCToolkit 707 * Method: initAppkit 708 * Signature: (Ljava/lang/ThreadGroup;)V 709 */ 710 JNIEXPORT void JNICALL 711 Java_sun_lwawt_macosx_LWCToolkit_initAppkit 712 (JNIEnv *env, jclass klass, jobject appkitThreadGroup, jboolean headless) { 713 JNF_COCOA_ENTER(env) 714 715 [ThreadUtilities setAppkitThreadGroup:(*env)->NewGlobalRef(env, appkitThreadGroup)]; 716 717 // Launcher sets this env variable if -XstartOnFirstThread is specified 718 char envVar[80]; 719 snprintf(envVar, sizeof(envVar), "JAVA_STARTED_ON_FIRST_THREAD_%d", getpid()); 720 if (getenv(envVar) != NULL) { 721 forceEmbeddedMode = YES; 722 unsetenv(envVar); 723 } 724 725 if (isSWTInWebStart(env)) { 726 forceEmbeddedMode = YES; 727 } 728 729 [AWTStarter start:headless ? YES : NO]; 730 731 JNF_COCOA_EXIT(env) 732 } 733 734 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { 735 OSXAPP_SetJavaVM(vm); 736 737 // We need to let Foundation know that this is a multithreaded application, if it isn't already. 738 if (![NSThread isMultiThreaded]) { 739 [NSThread detachNewThreadSelector:nil toTarget:nil withObject:nil]; 740 } 741 742 return JNI_VERSION_1_4; 743 } 744 745 /* 746 * Class: sun_lwawt_macosx_LWCToolkit 747 * Method: isEmbedded 748 * Signature: ()Z 749 */ 750 JNIEXPORT jboolean JNICALL 751 Java_sun_lwawt_macosx_LWCToolkit_isEmbedded 752 (JNIEnv *env, jclass klass) { 753 return isEmbedded ? JNI_TRUE : JNI_FALSE; 754 } 755