/*
 * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#import <dlfcn.h>
#import <pthread.h>
#import <objc/runtime.h>
#import <Cocoa/Cocoa.h>
#import <Security/AuthSession.h>

#include "jni_util.h"
#import "LWCToolkit.h"
#import "ThreadUtilities.h"
#import "CSystemColors.h"
#import  "NSApplicationAWT.h"
#import "PropertiesUtilities.h"
#import "ApplicationDelegate.h"

#import "sun_lwawt_macosx_LWCToolkit.h"

#import "sizecalc.h"

#import <JavaRuntimeSupport/JavaRuntimeSupport.h>

// SCROLL PHASE STATE
#define SCROLL_PHASE_UNSUPPORTED 1
#define SCROLL_PHASE_BEGAN 2
#define SCROLL_PHASE_CONTINUED 3
#define SCROLL_PHASE_CANCELLED 4
#define SCROLL_PHASE_ENDED 5

int gNumberOfButtons;
jint* gButtonDownMasks;

// Indicates that the app has been started with -XstartOnFirstThread
// (directly or via WebStart settings), and AWT should not run its
// own event loop in this mode. Even if a loop isn't running yet,
// we expect an embedder (e.g. SWT) to start it some time later.
static BOOL forceEmbeddedMode = NO;

// Indicates if awt toolkit is embedded into another UI toolkit
static BOOL isEmbedded = NO;

// This is the data necessary to have JNI_OnLoad wait for AppKit to start.
static BOOL sAppKitStarted = NO;
static pthread_mutex_t sAppKitStarted_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t sAppKitStarted_cv = PTHREAD_COND_INITIALIZER;

@implementation AWTToolkit

static long eventCount;

+ (long) getEventCount{
    return eventCount;
}

+ (void) eventCountPlusPlus{
    eventCount++;
}

+ (jint) scrollStateWithEvent: (NSEvent*) event {

    if ([event type] != NSScrollWheel) {
        return 0;
    }
    
    NSEventPhase phase = [event phase];
    NSEventPhase momentumPhase = [event momentumPhase];
    
    if (!phase && !momentumPhase) return SCROLL_PHASE_UNSUPPORTED;
    switch (phase) {
        case NSEventPhaseBegan: return SCROLL_PHASE_BEGAN;
        case NSEventPhaseCancelled: return SCROLL_PHASE_CANCELLED;
        case NSEventPhaseEnded: return SCROLL_PHASE_ENDED;
        default: return SCROLL_PHASE_CONTINUED;
    }
}
@end


@interface AWTRunLoopObject : NSObject {
    BOOL _shouldEndRunLoop;
}
@end

@implementation AWTRunLoopObject

- (id) init {
    self = [super init];
    if (self != nil) {
        _shouldEndRunLoop = NO;
    }
    return self;
}

- (BOOL) shouldEndRunLoop {
    return _shouldEndRunLoop;
}

- (void) endRunLoop {
    _shouldEndRunLoop = YES;
}

@end

@interface JavaRunnable : NSObject { }
@property jobject runnable;
- (id)initWithRunnable:(jobject)gRunnable;
- (void)perform;
@end

@implementation JavaRunnable
@synthesize runnable = _runnable;

- (id)initWithRunnable:(jobject)gRunnable {
    if (self = [super init]) {
        self.runnable = gRunnable;
    }
    return self;
}

- (void)dealloc {
    JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
    if (self.runnable) {
        (*env)->DeleteGlobalRef(env, self.runnable);
    }
    [super dealloc];
}

- (void)perform {
    JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
    static JNF_CLASS_CACHE(sjc_Runnable, "java/lang/Runnable");
    static JNF_MEMBER_CACHE(jm_Runnable_run, sjc_Runnable, "run", "()V");
    JNFCallVoidMethod(env, self.runnable, jm_Runnable_run);
    [self release];
}
@end

void setBusy(BOOL busy) {
    AWT_ASSERT_APPKIT_THREAD;

    JNIEnv *env = [ThreadUtilities getJNIEnv];
    static JNF_CLASS_CACHE(jc_AWTAutoShutdown, "sun/awt/AWTAutoShutdown");

    if (busy) {
        static JNF_STATIC_MEMBER_CACHE(jm_notifyBusyMethod, jc_AWTAutoShutdown, "notifyToolkitThreadBusy", "()V");
        JNFCallStaticVoidMethod(env, jm_notifyBusyMethod);
    } else {
        static JNF_STATIC_MEMBER_CACHE(jm_notifyFreeMethod, jc_AWTAutoShutdown, "notifyToolkitThreadFree", "()V");
        JNFCallStaticVoidMethod(env, jm_notifyFreeMethod);
    }
}

static void setUpAWTAppKit(BOOL installObservers)
{
    if (installObservers) {
        AWT_STARTUP_LOG(@"Setting up busy observers");

        // Add CFRunLoopObservers to call into AWT so that AWT knows that the
        //  AWT thread (which is the AppKit main thread) is alive. This way AWT
        //  will not automatically shutdown.
        CFRunLoopObserverRef busyObserver = CFRunLoopObserverCreateWithHandler(
                                               NULL,                        // CFAllocator
                                               kCFRunLoopAfterWaiting,      // CFOptionFlags
                                               true,                        // repeats
                                               NSIntegerMax,                // order
                                               ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
                                                   setBusy(YES);
                                               });

        CFRunLoopObserverRef notBusyObserver = CFRunLoopObserverCreateWithHandler(
                                                NULL,                        // CFAllocator
                                                kCFRunLoopBeforeWaiting,     // CFOptionFlags
                                                true,                        // repeats
                                                NSIntegerMin,                // order
                                                ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
                                                    setBusy(NO);
                                                });

        CFRunLoopRef runLoop = [[NSRunLoop currentRunLoop] getCFRunLoop];
        CFRunLoopAddObserver(runLoop, busyObserver, kCFRunLoopDefaultMode);
        CFRunLoopAddObserver(runLoop, notBusyObserver, kCFRunLoopDefaultMode);

        CFRelease(busyObserver);
        CFRelease(notBusyObserver);

        setBusy(YES);
    }

    JNIEnv* env = [ThreadUtilities getJNIEnv];
    static JNF_CLASS_CACHE(jc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit");
    static JNF_STATIC_MEMBER_CACHE(jsm_installToolkitThreadInJava, jc_LWCToolkit, "installToolkitThreadInJava", "()V");
    JNFCallStaticVoidMethod(env, jsm_installToolkitThreadInJava);
}

BOOL isSWTInWebStart(JNIEnv* env) {
    NSString *swtWebStart = [PropertiesUtilities javaSystemPropertyForKey:@"com.apple.javaws.usingSWT" withEnv:env];
    return [@"true" isCaseInsensitiveLike:swtWebStart];
}

static void AWT_NSUncaughtExceptionHandler(NSException *exception) {
    NSLog(@"Apple AWT Internal Exception: %@", [exception description]);
}

@interface AWTStarter : NSObject
+ (void)start:(BOOL)headless;
+ (void)starter:(BOOL)onMainThread headless:(BOOL)headless;
+ (void)appKitIsRunning:(id)arg;
@end

@implementation AWTStarter

+ (BOOL) isConnectedToWindowServer {
    SecuritySessionId session_id;
    SessionAttributeBits session_info;
    OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info);
    if (status != noErr) return NO;
    if (!(session_info & sessionHasGraphicAccess)) return NO;
    return YES;
}

+ (BOOL) markAppAsDaemon {
    id jrsAppKitAWTClass = objc_getClass("JRSAppKitAWT");
    SEL markAppSel = @selector(markAppIsDaemon);
    if (![jrsAppKitAWTClass respondsToSelector:markAppSel]) return NO;
    return [jrsAppKitAWTClass performSelector:markAppSel] ? YES : NO;
}

+ (void)appKitIsRunning:(id)arg {
    AWT_ASSERT_APPKIT_THREAD;
    AWT_STARTUP_LOG(@"About to message AppKit started");

    // Signal that AppKit has started (or is already running).
    pthread_mutex_lock(&sAppKitStarted_mutex);
    sAppKitStarted = YES;
    pthread_cond_signal(&sAppKitStarted_cv);
    pthread_mutex_unlock(&sAppKitStarted_mutex);

    AWT_STARTUP_LOG(@"Finished messaging AppKit started");
}

+ (void)start:(BOOL)headless
{
    // onMainThread is NOT the same at SWT mode!
    // If the JVM was started on the first thread for SWT, but the SWT loads the AWT on a secondary thread,
    // onMainThread here will be false but SWT mode will be true.  If we are currently on the main thread, we don't
    // need to throw AWT startup over to another thread.
    BOOL onMainThread = [NSThread isMainThread];

    NSString* msg = [NSString stringWithFormat:@"+[AWTStarter start headless:%d] { onMainThread:%d }", headless, onMainThread];
    AWT_STARTUP_LOG(msg);

    if (!headless)
    {
        // Listen for the NSApp to start. This indicates that JNI_OnLoad can proceed.
        //  It must wait because there is a chance that another java thread will grab
        //  the AppKit lock before the +[NSApplication sharedApplication] returns.
        //  See <rdar://problem/3492666> for an example.
        [[NSNotificationCenter defaultCenter] addObserver:[AWTStarter class]
                                                 selector:@selector(appKitIsRunning:)
                                                     name:NSApplicationDidFinishLaunchingNotification
                                                   object:nil];

        AWT_STARTUP_LOG(@"+[AWTStarter start:::]: registered NSApplicationDidFinishLaunchingNotification");
    }

    [ThreadUtilities performOnMainThreadWaiting:NO block:^() {
        [AWTStarter starter:onMainThread headless:headless];
    }];


    if (!headless && !onMainThread) {

        AWT_STARTUP_LOG(@"about to wait on AppKit startup mutex");

        // Wait here for AppKit to have started (or for AWT to have been loaded into
        //  an already running NSApplication).
        pthread_mutex_lock(&sAppKitStarted_mutex);
        while (sAppKitStarted == NO) {
            pthread_cond_wait(&sAppKitStarted_cv, &sAppKitStarted_mutex);
        }
        pthread_mutex_unlock(&sAppKitStarted_mutex);

        // AWT gets here AFTER +[AWTStarter appKitIsRunning:] is called.
        AWT_STARTUP_LOG(@"got out of the AppKit startup mutex");
    }

    if (!headless) {
        // Don't set the delegate until the NSApplication has been created and
        // its finishLaunching has initialized it.
        //  ApplicationDelegate is the support code for com.apple.eawt.
        [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
            id<NSApplicationDelegate> delegate = [ApplicationDelegate sharedDelegate];
            if (delegate != nil) {
                OSXAPP_SetApplicationDelegate(delegate);
            }
        }];
    }
}

+ (void)starter:(BOOL)wasOnMainThread headless:(BOOL)headless {
    NSAutoreleasePool *pool = [NSAutoreleasePool new];
    // Add the exception handler of last resort
    NSSetUncaughtExceptionHandler(AWT_NSUncaughtExceptionHandler);

    // Headless mode trumps either ordinary AWT or SWT-in-AWT mode.  Declare us a daemon and return.
    if (headless) {
        // Note that we don't install run loop observers in headless mode
        // because we don't need them (see 7174704)
        if (!forceEmbeddedMode) {
            setUpAWTAppKit(false);
        }
        [AWTStarter markAppAsDaemon];
        return;
    }

    if (forceEmbeddedMode) {
        AWT_STARTUP_LOG(@"in SWT or SWT/WebStart mode");

        // Init a default NSApplication instance instead of the NSApplicationAWT.
        // Note that [NSApp isRunning] will return YES after that, though
        // this behavior isn't specified anywhere. We rely on that.
        NSApplicationLoad();
    }

    // This will create a NSApplicationAWT for standalone AWT programs, unless there is
    //  already a NSApplication instance. If there is already a NSApplication instance,
    //  and -[NSApplication isRunning] returns YES, AWT is embedded inside another
    //  AppKit Application.
    NSApplication *app = [NSApplicationAWT sharedApplication];
    isEmbedded = ![NSApp isKindOfClass:[NSApplicationAWT class]];

    if (!isEmbedded) {
        // Install run loop observers and set the AppKit Java thread name
        setUpAWTAppKit(true);
    }

    // AWT gets to this point BEFORE NSApplicationDidFinishLaunchingNotification is sent.
    if (![app isRunning]) {
        AWT_STARTUP_LOG(@"+[AWTStarter startAWT]: ![app isRunning]");
        // This is where the AWT AppKit thread parks itself to process events.
        [NSApplicationAWT runAWTLoopWithApp: app];
    } else {
        // We're either embedded, or showing a splash screen
        if (isEmbedded) {
            AWT_STARTUP_LOG(@"running embedded");

            // We don't track if the runloop is busy, so set it free to let AWT finish when it needs
            setBusy(NO);
        } else {
            AWT_STARTUP_LOG(@"running after showing a splash screen");
        }

        // Signal so that JNI_OnLoad can proceed.
        if (!wasOnMainThread) [AWTStarter appKitIsRunning:nil];

        // Proceed to exit this call as there is no reason to run the NSApplication event loop.
    }

    [pool drain];
}

@end

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    nativeSyncQueue
 * Signature: (J)Z
 */
JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_nativeSyncQueue
(JNIEnv *env, jobject self, jlong timeout)
{
    long currentEventNum = [AWTToolkit getEventCount];

    NSApplication* sharedApp = [NSApplication sharedApplication];
    if ([sharedApp isKindOfClass:[NSApplicationAWT class]]) {
        NSApplicationAWT* theApp = (NSApplicationAWT*)sharedApp;
        // We use two different API to post events to the application,
        //  - [NSApplication postEvent]
        //  - CGEventPost(), see CRobot.m
        // It was found that if we post an event via CGEventPost in robot and
        // immediately after this we will post the second event via
        // [NSApp postEvent] then sometimes the second event will be handled
        // first. The opposite isn't proved, but we use both here to be safer.
        [theApp postDummyEvent:false];
        [theApp waitForDummyEvent:timeout / 2.0];
        [theApp postDummyEvent:true];
        [theApp waitForDummyEvent:timeout / 2.0];

    } else {
        // could happen if we are embedded inside SWT application,
        // in this case just spin a single empty block through
        // the event loop to give it a chance to process pending events
        [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){}];
    }

    if (([AWTToolkit getEventCount] - currentEventNum) != 0) {
        return JNI_TRUE;
    }

    return JNI_FALSE;
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    flushNativeSelectors
 * Signature: ()J
 */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_flushNativeSelectors
(JNIEnv *env, jclass clz)
{
JNF_COCOA_ENTER(env);
        [ThreadUtilities performOnMainThreadWaiting:YES block:^(){}];
JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    beep
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_LWCToolkit_beep
(JNIEnv *env, jobject self)
{
    NSBeep(); // produces both sound and visual flash, if configured in System Preferences
}

static UInt32 RGB(NSColor *c) {
    c = [c colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
    if (c == nil)
    {
        return -1; // opaque white
    }

    CGFloat r, g, b, a;
    [c getRed:&r green:&g blue:&b alpha:&a];

    UInt32 ir = (UInt32) (r*255+0.5),
    ig = (UInt32) (g*255+0.5),
    ib = (UInt32) (b*255+0.5),
    ia = (UInt32) (a*255+0.5);

    //    NSLog(@"%@ %d, %d, %d", c, ir, ig, ib);

    return ((ia & 0xFF) << 24) | ((ir & 0xFF) << 16) | ((ig & 0xFF) << 8) | ((ib & 0xFF) << 0);
}

BOOL doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) {
    jint len = (*env)->GetArrayLength(env, jColors);

    UInt32 colorsArray[len];
    UInt32 *colors = colorsArray;

    [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
        NSUInteger i;
        for (i = 0; i < len; i++) {
            colors[i] = RGB([CSystemColors getColor:i useAppleColor:useAppleColors]);
        }
    }];

    jint *_colors = (*env)->GetPrimitiveArrayCritical(env, jColors, 0);
    if (_colors == NULL) {
        return NO;
    }
    memcpy(_colors, colors, len * sizeof(UInt32));
    (*env)->ReleasePrimitiveArrayCritical(env, jColors, _colors, 0);
    return YES;
}

/**
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    loadNativeColors
 * Signature: ([I[I)V
 */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_loadNativeColors
(JNIEnv *env, jobject peer, jintArray jSystemColors, jintArray jAppleColors)
{
JNF_COCOA_ENTER(env);
    if (doLoadNativeColors(env, jSystemColors, NO)) {
        doLoadNativeColors(env, jAppleColors, YES);
    }
JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    createAWTRunLoopMediator
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_LWCToolkit_createAWTRunLoopMediator
(JNIEnv *env, jclass clz)
{
AWT_ASSERT_APPKIT_THREAD;

    jlong result;

JNF_COCOA_ENTER(env);
    // We double retain because this object is owned by both main thread and "other" thread
    // We release in both doAWTRunLoop and stopAWTRunLoop
    result = ptr_to_jlong([[[AWTRunLoopObject alloc] init] retain]);
JNF_COCOA_EXIT(env);

    return result;
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    doAWTRunLoopImpl
 * Signature: (JZZ)V
 */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoopImpl
(JNIEnv *env, jclass clz, jlong mediator, jboolean processEvents, jboolean inAWT)
{
AWT_ASSERT_APPKIT_THREAD;
JNF_COCOA_ENTER(env);

    AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator);

    if (mediatorObject == nil) return;

    // Don't use acceptInputForMode because that doesn't setup autorelease pools properly
    BOOL isRunning = true;
    while (![mediatorObject shouldEndRunLoop] && isRunning) {
        isRunning = [[NSRunLoop currentRunLoop] runMode:(inAWT ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode)
                                             beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]];
        if (processEvents) {
            //We do not spin a runloop here as date is nil, so does not matter which mode to use
            // Processing all events excluding NSApplicationDefined which need to be processed
            // on the main loop only (those events are intended for disposing resources)
            NSEvent *event;
            if ((event = [NSApp nextEventMatchingMask:(NSAnyEventMask & ~NSApplicationDefinedMask)
                                           untilDate:nil
                                              inMode:NSDefaultRunLoopMode
                                             dequeue:YES]) != nil) {
                [NSApp sendEvent:event];
            }

        }
    }
    [mediatorObject release];
JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    stopAWTRunLoop
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_stopAWTRunLoop
(JNIEnv *env, jclass clz, jlong mediator)
{
JNF_COCOA_ENTER(env);

    AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator);

    [ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO];

    [mediatorObject release];

JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    performOnMainThreadAfterDelay
 * Signature: (Ljava/lang/Runnable;J)V
 */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_performOnMainThreadAfterDelay
(JNIEnv *env, jclass clz, jobject runnable, jlong delay)
{
JNF_COCOA_ENTER(env);
    jobject gRunnable = (*env)->NewGlobalRef(env, runnable);
    CHECK_NULL(gRunnable);
    [ThreadUtilities performOnMainThreadWaiting:NO block:^() {
        JavaRunnable* performer = [[JavaRunnable alloc] initWithRunnable:gRunnable];
        [performer performSelector:@selector(perform) withObject:nil afterDelay:(delay/1000.0)];
    }];
JNF_COCOA_EXIT(env);
}


/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    isCapsLockOn
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isCapsLockOn
(JNIEnv *env, jobject self)
{
    __block jboolean isOn = JNI_FALSE;
    [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
        NSUInteger modifiers = [NSEvent modifierFlags];
        isOn = (modifiers & NSAlphaShiftKeyMask) != 0;
    }];

    return isOn;
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    isApplicationActive
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isApplicationActive
(JNIEnv *env, jclass clazz)
{
    __block jboolean active = JNI_FALSE;

JNF_COCOA_ENTER(env);

    [ThreadUtilities performOnMainThreadWaiting:YES block:^() {
        active = (jboolean)[NSRunningApplication currentApplication].active;
    }];

JNF_COCOA_EXIT(env);

    return active;
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    activateApplicationIgnoringOtherApps
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_activateApplicationIgnoringOtherApps
(JNIEnv *env, jclass clazz)
{
    JNF_COCOA_ENTER(env);
    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
        if(![NSApp isActive]){
            [NSApp activateIgnoringOtherApps:YES];
        }
    }];
    JNF_COCOA_EXIT(env);
}


/*
 * Class:     sun_awt_SunToolkit
 * Method:    closeSplashScreen
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv *env, jclass cls)
{
    void *hSplashLib = dlopen(0, RTLD_LAZY);
    if (!hSplashLib) return;

    void (*splashClose)() = dlsym(hSplashLib, "SplashClose");
    if (splashClose) {
        splashClose();
    }
    dlclose(hSplashLib);
}


// TODO: definitely doesn't belong here (copied from fontpath.c in the
// solaris tree)...

JNIEXPORT jstring JNICALL
Java_sun_font_FontManager_getFontPath
(JNIEnv *env, jclass obj, jboolean noType1)
{
    return JNFNSToJavaString(env, @"/Library/Fonts");
}

// This isn't yet used on unix, the implementation is added since shared
// code calls this method in preparation for future use.
JNIEXPORT void JNICALL
Java_sun_font_FontManager_populateFontFileNameMap
(JNIEnv *env, jclass obj, jobject fontToFileMap, jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale)
{

}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    initIDs
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_LWCToolkit_initIDs
(JNIEnv *env, jclass klass) {

    JNF_COCOA_ENTER(env)

    gNumberOfButtons = sun_lwawt_macosx_LWCToolkit_BUTTONS;

    jclass inputEventClazz = (*env)->FindClass(env, "java/awt/event/InputEvent");
    CHECK_NULL(inputEventClazz);
    jmethodID getButtonDownMasksID = (*env)->GetStaticMethodID(env, inputEventClazz, "getButtonDownMasks", "()[I");
    CHECK_NULL(getButtonDownMasksID);
    jintArray obj = (jintArray)(*env)->CallStaticObjectMethod(env, inputEventClazz, getButtonDownMasksID);
    jint * tmp = (*env)->GetIntArrayElements(env, obj, JNI_FALSE);
    CHECK_NULL(tmp);

    gButtonDownMasks = (jint*)SAFE_SIZE_ARRAY_ALLOC(malloc, sizeof(jint), gNumberOfButtons);
    if (gButtonDownMasks == NULL) {
        gNumberOfButtons = 0;
        (*env)->ReleaseIntArrayElements(env, obj, tmp, JNI_ABORT);
        JNU_ThrowOutOfMemoryError(env, NULL);
        return;
    }

    int i;
    for (i = 0; i < gNumberOfButtons; i++) {
        gButtonDownMasks[i] = tmp[i];
    }

    (*env)->ReleaseIntArrayElements(env, obj, tmp, 0);
    (*env)->DeleteLocalRef(env, obj);

    JNF_COCOA_EXIT(env)
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    initAppkit
 * Signature: (Ljava/lang/ThreadGroup;)V
 */
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_LWCToolkit_initAppkit
(JNIEnv *env, jclass klass, jobject appkitThreadGroup, jboolean headless) {
    JNF_COCOA_ENTER(env)

    [ThreadUtilities setAppkitThreadGroup:(*env)->NewGlobalRef(env, appkitThreadGroup)];

    // Launcher sets this env variable if -XstartOnFirstThread is specified
    char envVar[80];
    snprintf(envVar, sizeof(envVar), "JAVA_STARTED_ON_FIRST_THREAD_%d", getpid());
    if (getenv(envVar) != NULL) {
        forceEmbeddedMode = YES;
        unsetenv(envVar);
    }

    if (isSWTInWebStart(env)) {
        forceEmbeddedMode = YES;
    }

    [AWTStarter start:headless ? YES : NO];

    JNF_COCOA_EXIT(env)
}

JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
    OSXAPP_SetJavaVM(vm);

    // We need to let Foundation know that this is a multithreaded application,
    // if it isn't already.
    if (![NSThread isMultiThreaded]) {
        [[[[NSThread alloc] init] autorelease] start];
    }

    return JNI_VERSION_1_4;
}

/*
 * Class:     sun_lwawt_macosx_LWCToolkit
 * Method:    isEmbedded
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL
Java_sun_lwawt_macosx_LWCToolkit_isEmbedded
(JNIEnv *env, jclass klass) {
    return isEmbedded ? JNI_TRUE : JNI_FALSE;
}

