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