< prev index next >

src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m

Print this page
rev 54094 : 8257853: Remove dependencies on JNF's JNI utility functions in AWT and 2D code
rev 54096 : 8259651: [macOS] Replace JNF_COCOA_ENTER/EXIT macros
rev 54098 : 8260616: Removing remaining JNF dependencies in the java.desktop module
8259729: Missed JNFInstanceOf -> IsInstanceOf conversion


  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 // SCROLL PHASE STATE
  47 #define SCROLL_PHASE_UNSUPPORTED 1
  48 #define SCROLL_PHASE_BEGAN 2
  49 #define SCROLL_PHASE_CONTINUED 3
  50 #define SCROLL_PHASE_MOMENTUM_BEGAN 4
  51 #define SCROLL_PHASE_ENDED 5
  52 


 167 @implementation JavaRunnable
 168 @synthesize runnable = _runnable;
 169 
 170 - (id)initWithRunnable:(jobject)gRunnable {
 171     if (self = [super init]) {
 172         self.runnable = gRunnable;
 173     }
 174     return self;
 175 }
 176 
 177 - (void)dealloc {
 178     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
 179     if (self.runnable) {
 180         (*env)->DeleteGlobalRef(env, self.runnable);
 181     }
 182     [super dealloc];
 183 }
 184 
 185 - (void)perform {
 186     JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
 187     static JNF_CLASS_CACHE(sjc_Runnable, "java/lang/Runnable");
 188     static JNF_MEMBER_CACHE(jm_Runnable_run, sjc_Runnable, "run", "()V");
 189     JNFCallVoidMethod(env, self.runnable, jm_Runnable_run);

 190     [self release];
 191 }
 192 @end
 193 
 194 void setBusy(BOOL busy) {
 195     AWT_ASSERT_APPKIT_THREAD;
 196 
 197     JNIEnv *env = [ThreadUtilities getJNIEnv];
 198     static JNF_CLASS_CACHE(jc_AWTAutoShutdown, "sun/awt/AWTAutoShutdown");
 199 
 200     if (busy) {
 201         static JNF_STATIC_MEMBER_CACHE(jm_notifyBusyMethod, jc_AWTAutoShutdown, "notifyToolkitThreadBusy", "()V");
 202         JNFCallStaticVoidMethod(env, jm_notifyBusyMethod);
 203     } else {
 204         static JNF_STATIC_MEMBER_CACHE(jm_notifyFreeMethod, jc_AWTAutoShutdown, "notifyToolkitThreadFree", "()V");
 205         JNFCallStaticVoidMethod(env, jm_notifyFreeMethod);
 206     }

 207 }
 208 
 209 static void setUpAWTAppKit(BOOL installObservers)
 210 {
 211     if (installObservers) {
 212         AWT_STARTUP_LOG(@"Setting up busy observers");
 213 
 214         // Add CFRunLoopObservers to call into AWT so that AWT knows that the
 215         //  AWT thread (which is the AppKit main thread) is alive. This way AWT
 216         //  will not automatically shutdown.
 217         CFRunLoopObserverRef busyObserver = CFRunLoopObserverCreateWithHandler(
 218                                                NULL,                        // CFAllocator
 219                                                kCFRunLoopAfterWaiting,      // CFOptionFlags
 220                                                true,                        // repeats
 221                                                NSIntegerMax,                // order
 222                                                ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
 223                                                    setBusy(YES);
 224                                                });
 225 
 226         CFRunLoopObserverRef notBusyObserver = CFRunLoopObserverCreateWithHandler(
 227                                                 NULL,                        // CFAllocator
 228                                                 kCFRunLoopBeforeWaiting,     // CFOptionFlags
 229                                                 true,                        // repeats
 230                                                 NSIntegerMin,                // order
 231                                                 ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
 232                                                     setBusy(NO);
 233                                                 });
 234 
 235         CFRunLoopRef runLoop = [[NSRunLoop currentRunLoop] getCFRunLoop];
 236         CFRunLoopAddObserver(runLoop, busyObserver, kCFRunLoopDefaultMode);
 237         CFRunLoopAddObserver(runLoop, notBusyObserver, kCFRunLoopDefaultMode);
 238 
 239         CFRelease(busyObserver);
 240         CFRelease(notBusyObserver);
 241 
 242         setBusy(YES);
 243     }
 244 
 245     JNIEnv* env = [ThreadUtilities getJNIEnv];
 246     static JNF_CLASS_CACHE(jc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
 247     static JNF_STATIC_MEMBER_CACHE(jsm_installToolkitThreadInJava, jc_LWCToolkit, "installToolkitThreadInJava", "()V");
 248     JNFCallStaticVoidMethod(env, jsm_installToolkitThreadInJava);


 249 }
 250 
 251 BOOL isSWTInWebStart(JNIEnv* env) {
 252     NSString *swtWebStart = [PropertiesUtilities javaSystemPropertyForKey:@"com.apple.javaws.usingSWT" withEnv:env];
 253     return [@"true" isCaseInsensitiveLike:swtWebStart];
 254 }
 255 
 256 static void AWT_NSUncaughtExceptionHandler(NSException *exception) {
 257     NSLog(@"Apple AWT Internal Exception: %@", [exception description]);
 258 }
 259 
 260 @interface AWTStarter : NSObject
 261 + (void)start:(BOOL)headless;
 262 + (void)starter:(BOOL)onMainThread headless:(BOOL)headless;
 263 + (void)appKitIsRunning:(id)arg;
 264 @end
 265 
 266 @implementation AWTStarter
 267 
 268 + (BOOL) isConnectedToWindowServer {


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

 756     jint * tmp = (*env)->GetIntArrayElements(env, obj, JNI_FALSE);
 757     CHECK_NULL(tmp);
 758 
 759     gButtonDownMasks = (jint*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(jint), gNumberOfButtons);
 760     if (gButtonDownMasks == NULL) {
 761         gNumberOfButtons = 0;
 762         (*env)->ReleaseIntArrayElements(env, obj, tmp, JNI_ABORT);
 763         JNU_ThrowOutOfMemoryError(env, NULL);
 764         return;
 765     }
 766 
 767     int i;
 768     for (i = 0; i < gNumberOfButtons; i++) {
 769         gButtonDownMasks[i] = tmp[i];
 770     }
 771 
 772     (*env)->ReleaseIntArrayElements(env, obj, tmp, 0);
 773     (*env)->DeleteLocalRef(env, obj);
 774 
 775     JNF_COCOA_EXIT(env)
 776 }
 777 
 778 /*
 779  * Class:     sun_lwawt_macosx_LWCToolkit
 780  * Method:    initAppkit
 781  * Signature: (Ljava/lang/ThreadGroup;)V
 782  */
 783 JNIEXPORT void JNICALL
 784 Java_sun_lwawt_macosx_LWCToolkit_initAppkit
 785 (JNIEnv *env, jclass klass, jobject appkitThreadGroup, jboolean headless) {
 786     JNF_COCOA_ENTER(env)
 787 
 788     [ThreadUtilities setAppkitThreadGroup:(*env)->NewGlobalRef(env, appkitThreadGroup)];
 789 
 790     // Launcher sets this env variable if -XstartOnFirstThread is specified
 791     char envVar[80];
 792     snprintf(envVar, sizeof(envVar), "JAVA_STARTED_ON_FIRST_THREAD_%d", getpid());
 793     if (getenv(envVar) != NULL) {
 794         forceEmbeddedMode = YES;
 795         unsetenv(envVar);
 796     }
 797 
 798     if (isSWTInWebStart(env)) {
 799         forceEmbeddedMode = YES;
 800     }
 801 
 802     [AWTStarter start:headless ? YES : NO];
 803 
 804     JNF_COCOA_EXIT(env)
 805 }
 806 
 807 JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
 808     OSXAPP_SetJavaVM(vm);
 809 
 810     // We need to let Foundation know that this is a multithreaded application,
 811     // if it isn't already.
 812     if (![NSThread isMultiThreaded]) {
 813         [[[[NSThread alloc] init] autorelease] start];
 814     }
 815 
 816     return JNI_VERSION_1_4;
 817 }
 818 
 819 /*
 820  * Class:     sun_lwawt_macosx_LWCToolkit
 821  * Method:    isEmbedded
 822  * Signature: ()Z
 823  */
 824 JNIEXPORT jboolean JNICALL




  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 #import "JNIUtilities.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 // SCROLL PHASE STATE
  47 #define SCROLL_PHASE_UNSUPPORTED 1
  48 #define SCROLL_PHASE_BEGAN 2
  49 #define SCROLL_PHASE_CONTINUED 3
  50 #define SCROLL_PHASE_MOMENTUM_BEGAN 4
  51 #define SCROLL_PHASE_ENDED 5
  52 


 167 @implementation JavaRunnable
 168 @synthesize runnable = _runnable;
 169 
 170 - (id)initWithRunnable:(jobject)gRunnable {
 171     if (self = [super init]) {
 172         self.runnable = gRunnable;
 173     }
 174     return self;
 175 }
 176 
 177 - (void)dealloc {
 178     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
 179     if (self.runnable) {
 180         (*env)->DeleteGlobalRef(env, self.runnable);
 181     }
 182     [super dealloc];
 183 }
 184 
 185 - (void)perform {
 186     JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
 187     DECLARE_CLASS(sjc_Runnable, "java/lang/Runnable");
 188     DECLARE_METHOD(jm_Runnable_run, sjc_Runnable, "run", "()V");
 189     (*env)->CallVoidMethod(env, self.runnable, jm_Runnable_run);
 190     CHECK_EXCEPTION();
 191     [self release];
 192 }
 193 @end
 194 
 195 void setBusy(BOOL busy) {
 196     AWT_ASSERT_APPKIT_THREAD;
 197 
 198     JNIEnv *env = [ThreadUtilities getJNIEnv];
 199     DECLARE_CLASS(jc_AWTAutoShutdown, "sun/awt/AWTAutoShutdown");
 200 
 201     if (busy) {
 202         DECLARE_STATIC_METHOD(jm_notifyBusyMethod, jc_AWTAutoShutdown, "notifyToolkitThreadBusy", "()V");
 203         (*env)->CallStaticVoidMethod(env, jc_AWTAutoShutdown, jm_notifyBusyMethod);
 204     } else {
 205         DECLARE_STATIC_METHOD(jm_notifyFreeMethod, jc_AWTAutoShutdown, "notifyToolkitThreadFree", "()V");
 206         (*env)->CallStaticVoidMethod(env, jc_AWTAutoShutdown, jm_notifyFreeMethod);
 207     }
 208      CHECK_EXCEPTION();
 209 }
 210 
 211 static void setUpAWTAppKit(BOOL installObservers)
 212 {
 213     if (installObservers) {
 214         AWT_STARTUP_LOG(@"Setting up busy observers");
 215 
 216         // Add CFRunLoopObservers to call into AWT so that AWT knows that the
 217         //  AWT thread (which is the AppKit main thread) is alive. This way AWT
 218         //  will not automatically shutdown.
 219         CFRunLoopObserverRef busyObserver = CFRunLoopObserverCreateWithHandler(
 220                                                NULL,                        // CFAllocator
 221                                                kCFRunLoopAfterWaiting,      // CFOptionFlags
 222                                                true,                        // repeats
 223                                                NSIntegerMax,                // order
 224                                                ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
 225                                                    setBusy(YES);
 226                                                });
 227 
 228         CFRunLoopObserverRef notBusyObserver = CFRunLoopObserverCreateWithHandler(
 229                                                 NULL,                        // CFAllocator
 230                                                 kCFRunLoopBeforeWaiting,     // CFOptionFlags
 231                                                 true,                        // repeats
 232                                                 NSIntegerMin,                // order
 233                                                 ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
 234                                                     setBusy(NO);
 235                                                 });
 236 
 237         CFRunLoopRef runLoop = [[NSRunLoop currentRunLoop] getCFRunLoop];
 238         CFRunLoopAddObserver(runLoop, busyObserver, kCFRunLoopDefaultMode);
 239         CFRunLoopAddObserver(runLoop, notBusyObserver, kCFRunLoopDefaultMode);
 240 
 241         CFRelease(busyObserver);
 242         CFRelease(notBusyObserver);
 243 
 244         setBusy(YES);
 245     }
 246 
 247     JNIEnv* env = [ThreadUtilities getJNIEnv];
 248     DECLARE_CLASS(jc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
 249     DECLARE_STATIC_METHOD(jsm_installToolkitThreadInJava, jc_LWCToolkit, "installToolkitThreadInJava", "()V");
 250     (*env)->CallStaticVoidMethod(env, jc_LWCToolkit, jsm_installToolkitThreadInJava);
 251     CHECK_EXCEPTION();
 252 
 253 }
 254 
 255 BOOL isSWTInWebStart(JNIEnv* env) {
 256     NSString *swtWebStart = [PropertiesUtilities javaSystemPropertyForKey:@"com.apple.javaws.usingSWT" withEnv:env];
 257     return [@"true" isCaseInsensitiveLike:swtWebStart];
 258 }
 259 
 260 static void AWT_NSUncaughtExceptionHandler(NSException *exception) {
 261     NSLog(@"Apple AWT Internal Exception: %@", [exception description]);
 262 }
 263 
 264 @interface AWTStarter : NSObject
 265 + (void)start:(BOOL)headless;
 266 + (void)starter:(BOOL)onMainThread headless:(BOOL)headless;
 267 + (void)appKitIsRunning:(id)arg;
 268 @end
 269 
 270 @implementation AWTStarter
 271 
 272 + (BOOL) isConnectedToWindowServer {


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


< prev index next >