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 #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 long currentEventNum = [AWTToolkit getEventCount]; 374 375 NSApplication* sharedApp = [NSApplication sharedApplication]; 376 if ([sharedApp isKindOfClass:[NSApplicationAWT class]]) { 377 NSApplicationAWT* theApp = (NSApplicationAWT*)sharedApp; 378 // We use two different API to post events to the application, 379 // - [NSApplication postEvent] 380 // - CGEventPost(), see CRobot.m 381 // It was found that if we post an event via CGEventPost in robot and 382 // immediately after this we will post the second event via 383 // [NSApp postEvent] then sometimes the second event will be handled 384 // first. The opposite isn't proved, but we use both here to be safer. 385 [theApp postDummyEvent:false]; 386 [theApp waitForDummyEvent:timeout / 2.0]; 387 [theApp postDummyEvent:true]; 388 [theApp waitForDummyEvent:timeout / 2.0]; 389 390 } else { 391 // could happen if we are embedded inside SWT application, 392 // in this case just spin a single empty block through 393 // the event loop to give it a chance to process pending events 394 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){}]; 395 } 396 397 if (([AWTToolkit getEventCount] - currentEventNum) != 0) { 398 return JNI_TRUE; 399 } 400 401 return JNI_FALSE; 402 } 403 404 /* 405 * Class: sun_lwawt_macosx_LWCToolkit 406 * Method: flushNativeSelectors 407 * Signature: ()J 408 */ 409 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_flushNativeSelectors 410 (JNIEnv *env, jclass clz) 411 { 412 JNF_COCOA_ENTER(env); 413 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){}]; 414 JNF_COCOA_EXIT(env); 415 } 416 417 /* 418 * Class: sun_lwawt_macosx_LWCToolkit 419 * Method: beep 420 * Signature: ()V 421 */ 422 JNIEXPORT void JNICALL 423 Java_sun_lwawt_macosx_LWCToolkit_beep 424 (JNIEnv *env, jobject self) 425 { 426 NSBeep(); // produces both sound and visual flash, if configured in System Preferences 427 } 428 429 static UInt32 RGB(NSColor *c) { 430 c = [c colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; 431 if (c == nil) 432 { 433 return -1; // opaque white 434 } 435 436 CGFloat r, g, b, a; 437 [c getRed:&r green:&g blue:&b alpha:&a]; 438 439 UInt32 ir = (UInt32) (r*255+0.5), 440 ig = (UInt32) (g*255+0.5), 441 ib = (UInt32) (b*255+0.5), 442 ia = (UInt32) (a*255+0.5); 443 444 // NSLog(@"%@ %d, %d, %d", c, ir, ig, ib); 445 446 return ((ia & 0xFF) << 24) | ((ir & 0xFF) << 16) | ((ig & 0xFF) << 8) | ((ib & 0xFF) << 0); 447 } 448 449 BOOL doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) { 450 jint len = (*env)->GetArrayLength(env, jColors); 451 452 UInt32 colorsArray[len]; 453 UInt32 *colors = colorsArray; 454 455 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ 456 NSUInteger i; 457 for (i = 0; i < len; i++) { 458 colors[i] = RGB([CSystemColors getColor:i useAppleColor:useAppleColors]); 459 } 460 }]; 461 462 jint *_colors = (*env)->GetPrimitiveArrayCritical(env, jColors, 0); 463 if (_colors == NULL) { 464 return NO; 465 } 466 memcpy(_colors, colors, len * sizeof(UInt32)); 467 (*env)->ReleasePrimitiveArrayCritical(env, jColors, _colors, 0); 468 return YES; 469 } 470 471 /** 472 * Class: sun_lwawt_macosx_LWCToolkit 473 * Method: loadNativeColors 474 * Signature: ([I[I)V 475 */ 476 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_loadNativeColors 477 (JNIEnv *env, jobject peer, jintArray jSystemColors, jintArray jAppleColors) 478 { 479 JNF_COCOA_ENTER(env); 480 if (doLoadNativeColors(env, jSystemColors, NO)) { 481 doLoadNativeColors(env, jAppleColors, YES); 482 } 483 JNF_COCOA_EXIT(env); 484 } 485 486 /* 487 * Class: sun_lwawt_macosx_LWCToolkit 488 * Method: createAWTRunLoopMediator 489 * Signature: ()J 490 */ 491 JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_LWCToolkit_createAWTRunLoopMediator 492 (JNIEnv *env, jclass clz) 493 { 494 AWT_ASSERT_APPKIT_THREAD; 495 496 jlong result; 497 498 JNF_COCOA_ENTER(env); 499 // We double retain because this object is owned by both main thread and "other" thread 500 // We release in both doAWTRunLoop and stopAWTRunLoop 501 result = ptr_to_jlong([[[AWTRunLoopObject alloc] init] retain]); 502 JNF_COCOA_EXIT(env); 503 504 return result; 505 } 506 507 /* 508 * Class: sun_lwawt_macosx_LWCToolkit 509 * Method: doAWTRunLoopImpl 510 * Signature: (JZZ)V 511 */ 512 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoopImpl 513 (JNIEnv *env, jclass clz, jlong mediator, jboolean processEvents, jboolean inAWT) 514 { 515 AWT_ASSERT_APPKIT_THREAD; 516 JNF_COCOA_ENTER(env); 517 518 AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator); 519 520 if (mediatorObject == nil) return; 521 522 // Don't use acceptInputForMode because that doesn't setup autorelease pools properly 523 BOOL isRunning = true; 524 while (![mediatorObject shouldEndRunLoop] && isRunning) { 525 isRunning = [[NSRunLoop currentRunLoop] runMode:(inAWT ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode) 526 beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]]; 527 if (processEvents) { 528 //We do not spin a runloop here as date is nil, so does not matter which mode to use 529 // Processing all events excluding NSApplicationDefined which need to be processed 530 // on the main loop only (those events are intended for disposing resources) 531 NSEvent *event; 532 if ((event = [NSApp nextEventMatchingMask:(NSAnyEventMask & ~NSApplicationDefined) 533 untilDate:nil 534 inMode:NSDefaultRunLoopMode 535 dequeue:YES]) != nil) { 536 [NSApp sendEvent:event]; 537 } 538 539 } 540 } 541 [mediatorObject release]; 542 JNF_COCOA_EXIT(env); 543 } 544 545 /* 546 * Class: sun_lwawt_macosx_LWCToolkit 547 * Method: stopAWTRunLoop 548 * Signature: (J)V 549 */ 550 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_stopAWTRunLoop 551 (JNIEnv *env, jclass clz, jlong mediator) 552 { 553 JNF_COCOA_ENTER(env); 554 555 AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator); 556 557 [ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO]; 558 559 [mediatorObject release]; 560 561 JNF_COCOA_EXIT(env); 562 } 563 564 /* 565 * Class: sun_lwawt_macosx_LWCToolkit 566 * Method: performOnMainThreadAfterDelay 567 * Signature: (Ljava/lang/Runnable;J)V 568 */ 569 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_performOnMainThreadAfterDelay 570 (JNIEnv *env, jclass clz, jobject runnable, jlong delay) 571 { 572 JNF_COCOA_ENTER(env); 573 jobject gRunnable = (*env)->NewGlobalRef(env, runnable); 574 CHECK_NULL(gRunnable); 575 [ThreadUtilities performOnMainThreadWaiting:NO block:^() { 576 JavaRunnable* performer = [[JavaRunnable alloc] initWithRunnable:gRunnable]; 577 [performer performSelector:@selector(perform) withObject:nil afterDelay:(delay/1000.0)]; 578 }]; 579 JNF_COCOA_EXIT(env); 580 } 581 582 583 /* 584 * Class: sun_lwawt_macosx_LWCToolkit 585 * Method: isCapsLockOn 586 * Signature: ()Z 587 */ 588 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isCapsLockOn 589 (JNIEnv *env, jobject self) 590 { 591 __block jboolean isOn = JNI_FALSE; 592 [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ 593 NSUInteger modifiers = [NSEvent modifierFlags]; 594 isOn = (modifiers & NSAlphaShiftKeyMask) != 0; 595 }]; 596 597 return isOn; 598 } 599 600 /* 601 * Class: sun_lwawt_macosx_LWCToolkit 602 * Method: isApplicationActive 603 * Signature: ()Z 604 */ 605 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isApplicationActive 606 (JNIEnv *env, jclass clazz) 607 { 608 __block jboolean active = JNI_FALSE; 609 610 JNF_COCOA_ENTER(env); 611 612 [ThreadUtilities performOnMainThreadWaiting:YES block:^() { 613 active = (jboolean)[NSRunningApplication currentApplication].active; 614 }]; 615 616 JNF_COCOA_EXIT(env); 617 618 return active; 619 } 620 621 /* 622 * Class: sun_lwawt_macosx_LWCToolkit 623 * Method: activateApplicationIgnoringOtherApps 624 * Signature: ()V 625 */ 626 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_activateApplicationIgnoringOtherApps 627 (JNIEnv *env, jclass clazz) 628 { 629 JNF_COCOA_ENTER(env); 630 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 631 if(![NSApp isActive]){ 632 [NSApp activateIgnoringOtherApps:YES]; 633 } 634 }]; 635 JNF_COCOA_EXIT(env); 636 } 637 638 639 /* 640 * Class: sun_awt_SunToolkit 641 * Method: closeSplashScreen 642 * Signature: ()V 643 */ 644 JNIEXPORT void JNICALL 645 Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv *env, jclass cls) 646 { 647 void *hSplashLib = dlopen(0, RTLD_LAZY); 648 if (!hSplashLib) return; 649 650 void (*splashClose)() = dlsym(hSplashLib, "SplashClose"); 651 if (splashClose) { 652 splashClose(); 653 } 654 dlclose(hSplashLib); 655 } 656 657 658 // TODO: definitely doesn't belong here (copied from fontpath.c in the 659 // solaris tree)... 660 661 JNIEXPORT jstring JNICALL 662 Java_sun_font_FontManager_getFontPath 663 (JNIEnv *env, jclass obj, jboolean noType1) 664 { 665 return JNFNSToJavaString(env, @"/Library/Fonts"); 666 } 667 668 // This isn't yet used on unix, the implementation is added since shared 669 // code calls this method in preparation for future use. 670 JNIEXPORT void JNICALL 671 Java_sun_font_FontManager_populateFontFileNameMap 672 (JNIEnv *env, jclass obj, jobject fontToFileMap, jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale) 673 { 674 675 } 676 677 /* 678 * Class: sun_lwawt_macosx_LWCToolkit 679 * Method: initIDs 680 * Signature: ()V 681 */ 682 JNIEXPORT void JNICALL 683 Java_sun_lwawt_macosx_LWCToolkit_initIDs 684 (JNIEnv *env, jclass klass) { 685 686 JNF_COCOA_ENTER(env) 687 688 gNumberOfButtons = sun_lwawt_macosx_LWCToolkit_BUTTONS; 689 690 jclass inputEventClazz = (*env)->FindClass(env, "java/awt/event/InputEvent"); 691 CHECK_NULL(inputEventClazz); 692 jmethodID getButtonDownMasksID = (*env)->GetStaticMethodID(env, inputEventClazz, "getButtonDownMasks", "()[I"); 693 CHECK_NULL(getButtonDownMasksID); 694 jintArray obj = (jintArray)(*env)->CallStaticObjectMethod(env, inputEventClazz, getButtonDownMasksID); 695 jint * tmp = (*env)->GetIntArrayElements(env, obj, JNI_FALSE); 696 CHECK_NULL(tmp); 697 698 gButtonDownMasks = (jint*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(jint), gNumberOfButtons); 699 if (gButtonDownMasks == NULL) { 700 gNumberOfButtons = 0; 701 (*env)->ReleaseIntArrayElements(env, obj, tmp, JNI_ABORT); 702 JNU_ThrowOutOfMemoryError(env, NULL); 703 return; 704 } 705 706 int i; 707 for (i = 0; i < gNumberOfButtons; i++) { 708 gButtonDownMasks[i] = tmp[i]; 709 } 710 711 (*env)->ReleaseIntArrayElements(env, obj, tmp, 0); 712 (*env)->DeleteLocalRef(env, obj); 713 714 JNF_COCOA_EXIT(env) 715 } 716 717 /* 718 * Class: sun_lwawt_macosx_LWCToolkit 719 * Method: initAppkit 720 * Signature: (Ljava/lang/ThreadGroup;)V 721 */ 722 JNIEXPORT void JNICALL 723 Java_sun_lwawt_macosx_LWCToolkit_initAppkit 724 (JNIEnv *env, jclass klass, jobject appkitThreadGroup, jboolean headless) { 725 JNF_COCOA_ENTER(env) 726 727 [ThreadUtilities setAppkitThreadGroup:(*env)->NewGlobalRef(env, appkitThreadGroup)]; 728 729 // Launcher sets this env variable if -XstartOnFirstThread is specified 730 char envVar[80]; 731 snprintf(envVar, sizeof(envVar), "JAVA_STARTED_ON_FIRST_THREAD_%d", getpid()); 732 if (getenv(envVar) != NULL) { 733 forceEmbeddedMode = YES; 734 unsetenv(envVar); 735 } 736 737 if (isSWTInWebStart(env)) { 738 forceEmbeddedMode = YES; 739 } 740 741 [AWTStarter start:headless ? YES : NO]; 742 743 JNF_COCOA_EXIT(env) 744 } 745 746 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { 747 OSXAPP_SetJavaVM(vm); 748 749 // We need to let Foundation know that this is a multithreaded application, if it isn't already. 750 if (![NSThread isMultiThreaded]) { 751 [NSThread detachNewThreadSelector:nil toTarget:nil withObject:nil]; 752 } 753 754 return JNI_VERSION_1_4; 755 } 756 757 /* 758 * Class: sun_lwawt_macosx_LWCToolkit 759 * Method: isEmbedded 760 * Signature: ()Z 761 */ 762 JNIEXPORT jboolean JNICALL 763 Java_sun_lwawt_macosx_LWCToolkit_isEmbedded 764 (JNIEnv *env, jclass klass) { 765 return isEmbedded ? JNI_TRUE : JNI_FALSE; 766 } 767