author | anthony |
Wed, 09 Oct 2013 15:34:53 +0400 | |
changeset 21241 | dc8cd488885d |
parent 20453 | e480eb64d2c2 |
child 23010 | 6dadb192ad81 |
permissions | -rw-r--r-- |
12047 | 1 |
/* |
2 |
* Copyright (c) 2011, 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 <pthread.h> |
|
27 |
#import <objc/runtime.h> |
|
28 |
#import <Cocoa/Cocoa.h> |
|
29 |
#import <Security/AuthSession.h> |
|
30 |
#import <JavaNativeFoundation/JavaNativeFoundation.h> |
|
31 |
#import <JavaRuntimeSupport/JavaRuntimeSupport.h> |
|
32 |
||
33 |
#import "NSApplicationAWT.h" |
|
34 |
#import "PropertiesUtilities.h" |
|
35 |
#import "ThreadUtilities.h" |
|
36 |
#import "AWT_debug.h" |
|
37 |
#import "ApplicationDelegate.h" |
|
38 |
||
39 |
#define DEBUG 0 |
|
40 |
||
41 |
||
42 |
// The symbol is defined in libosxapp.dylib (ThreadUtilities.m) |
|
43 |
extern JavaVM *jvm; |
|
44 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
45 |
// Indicates if AWT is running embedded (in SWT, FX, elsewhere) |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
46 |
static BOOL isEmbedded = NO; |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
47 |
|
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
48 |
// Indicates that the app has been started with -XstartOnFirstThread |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
49 |
// (directly or via WebStart settings), and AWT should not run its |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
50 |
// own event loop in this mode. Even if a loop isn't running yet, |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
51 |
// we expect an embedder (e.g. SWT) to start it some time later. |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
52 |
static BOOL forceEmbeddedMode = NO; |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
53 |
|
12047 | 54 |
static bool ShouldPrintVerboseDebugging() { |
55 |
static int debug = -1; |
|
56 |
if (debug == -1) { |
|
57 |
debug = (int)(getenv("JAVA_AWT_VERBOSE") != NULL) || (DEBUG != 0); |
|
58 |
} |
|
59 |
return (bool)debug; |
|
60 |
} |
|
61 |
||
62 |
// This is the data necessary to have JNI_OnLoad wait for AppKit to start. |
|
63 |
static BOOL sAppKitStarted = NO; |
|
64 |
static pthread_mutex_t sAppKitStarted_mutex = PTHREAD_MUTEX_INITIALIZER; |
|
65 |
static pthread_cond_t sAppKitStarted_cv = PTHREAD_COND_INITIALIZER; |
|
66 |
||
67 |
void setBusy(BOOL isBusy); |
|
68 |
static void BusyObserver(CFRunLoopObserverRef ref, CFRunLoopActivity what, void* arg); |
|
69 |
static void NotBusyObserver(CFRunLoopObserverRef ref, CFRunLoopActivity what, void* arg); |
|
70 |
static void AWT_NSUncaughtExceptionHandler(NSException *exception); |
|
71 |
||
72 |
static CFRunLoopObserverRef busyObserver = NULL; |
|
73 |
static CFRunLoopObserverRef notBusyObserver = NULL; |
|
74 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
75 |
static void setUpAWTAppKit() |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
76 |
{ |
12047 | 77 |
BOOL verbose = ShouldPrintVerboseDebugging(); |
78 |
if (verbose) AWT_DEBUG_LOG(@"setting up busy observers"); |
|
79 |
||
80 |
// Add CFRunLoopObservers to call into AWT so that AWT knows that the |
|
81 |
// AWT thread (which is the AppKit main thread) is alive. This way AWT |
|
82 |
// will not automatically shutdown. |
|
83 |
busyObserver = CFRunLoopObserverCreate( |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
84 |
NULL, // CFAllocator |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
85 |
kCFRunLoopAfterWaiting, // CFOptionFlags |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
86 |
true, // repeats |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
87 |
NSIntegerMax, // order |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
88 |
&BusyObserver, // CFRunLoopObserverCallBack |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
89 |
NULL); // CFRunLoopObserverContext |
12047 | 90 |
|
91 |
notBusyObserver = CFRunLoopObserverCreate( |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
92 |
NULL, // CFAllocator |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
93 |
kCFRunLoopBeforeWaiting, // CFOptionFlags |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
94 |
true, // repeats |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
95 |
NSIntegerMin, // order |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
96 |
&NotBusyObserver, // CFRunLoopObserverCallBack |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
97 |
NULL); // CFRunLoopObserverContext |
12047 | 98 |
|
99 |
CFRunLoopRef runLoop = [[NSRunLoop currentRunLoop] getCFRunLoop]; |
|
100 |
CFRunLoopAddObserver(runLoop, busyObserver, kCFRunLoopDefaultMode); |
|
101 |
CFRunLoopAddObserver(runLoop, notBusyObserver, kCFRunLoopDefaultMode); |
|
102 |
||
103 |
CFRelease(busyObserver); |
|
104 |
CFRelease(notBusyObserver); |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
105 |
|
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
106 |
setBusy(YES); |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
107 |
} |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
108 |
|
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
109 |
static void setUpAppKitThreadName() |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
110 |
{ |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
111 |
BOOL verbose = ShouldPrintVerboseDebugging(); |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
112 |
JNIEnv *env = [ThreadUtilities getJNIEnv]; |
12047 | 113 |
|
114 |
// Set the java name of the AppKit main thread appropriately. |
|
115 |
jclass threadClass = NULL; |
|
116 |
jstring name = NULL; |
|
117 |
jobject curThread = NULL; |
|
118 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
119 |
threadClass = (*env)->FindClass(env, "java/lang/Thread"); |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
120 |
if (threadClass == NULL || (*env)->ExceptionCheck(env)) goto cleanup; |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
121 |
jmethodID currentThreadID = (*env)->GetStaticMethodID(env, threadClass, "currentThread", "()Ljava/lang/Thread;"); |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
122 |
if (currentThreadID == NULL || (*env)->ExceptionCheck(env)) goto cleanup; |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
123 |
jmethodID setName = (*env)->GetMethodID(env, threadClass, "setName", "(Ljava/lang/String;)V"); |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
124 |
if (setName == NULL || (*env)->ExceptionCheck(env)) goto cleanup; |
12047 | 125 |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
126 |
curThread = (*env)->CallStaticObjectMethod(env, threadClass, currentThreadID); // AWT_THREADING Safe (known object) |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
127 |
if (curThread == NULL || (*env)->ExceptionCheck(env)) goto cleanup; |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
128 |
name = (*env)->NewStringUTF(env, "AWT-AppKit"); |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
129 |
if (name == NULL || (*env)->ExceptionCheck(env)) goto cleanup; |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
130 |
(*env)->CallVoidMethod(env, curThread, setName, name); // AWT_THREADING Safe (known object) |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
131 |
if ((*env)->ExceptionCheck(env)) goto cleanup; |
12047 | 132 |
|
133 |
cleanup: |
|
134 |
if (threadClass != NULL) { |
|
135 |
(*env)->DeleteLocalRef(env, threadClass); |
|
136 |
} |
|
137 |
if (name != NULL) { |
|
138 |
(*env)->DeleteLocalRef(env, name); |
|
139 |
} |
|
140 |
if (curThread != NULL) { |
|
141 |
(*env)->DeleteLocalRef(env, curThread); |
|
142 |
} |
|
143 |
if ((*env)->ExceptionCheck(env)) { |
|
144 |
(*env)->ExceptionDescribe(env); |
|
145 |
(*env)->ExceptionClear(env); |
|
146 |
} |
|
147 |
||
148 |
if (verbose) AWT_DEBUG_LOG(@"finished setting thread name"); |
|
149 |
} |
|
150 |
||
151 |
||
152 |
// Returns true if java believes it is running headless |
|
153 |
BOOL isHeadless(JNIEnv *env) { |
|
154 |
// Just access the property directly, instead of using GraphicsEnvironment.isHeadless. |
|
155 |
// This is because this may be called while AWT is being loaded, and calling AWT |
|
156 |
// while it is being loaded will deadlock. |
|
157 |
static JNF_CLASS_CACHE(jc_Toolkit, "java/awt/GraphicsEnvironment"); |
|
158 |
static JNF_STATIC_MEMBER_CACHE(jm_isHeadless, jc_Toolkit, "isHeadless", "()Z"); |
|
159 |
return JNFCallStaticBooleanMethod(env, jm_isHeadless); |
|
160 |
} |
|
161 |
||
162 |
BOOL isSWTInWebStart(JNIEnv* env) { |
|
163 |
NSString *swtWebStart = [PropertiesUtilities javaSystemPropertyForKey:@"com.apple.javaws.usingSWT" withEnv:env]; |
|
164 |
return [@"true" isCaseInsensitiveLike:swtWebStart]; |
|
165 |
} |
|
166 |
||
167 |
void setBusy(BOOL busy) { |
|
168 |
AWT_ASSERT_APPKIT_THREAD; |
|
169 |
||
170 |
JNIEnv *env = [ThreadUtilities getJNIEnv]; |
|
171 |
static JNF_CLASS_CACHE(jc_AWTAutoShutdown, "sun/awt/AWTAutoShutdown"); |
|
172 |
||
173 |
if (busy) { |
|
174 |
static JNF_STATIC_MEMBER_CACHE(jm_notifyBusyMethod, jc_AWTAutoShutdown, "notifyToolkitThreadBusy", "()V"); |
|
175 |
JNFCallStaticVoidMethod(env, jm_notifyBusyMethod); |
|
176 |
} else { |
|
177 |
static JNF_STATIC_MEMBER_CACHE(jm_notifyFreeMethod, jc_AWTAutoShutdown, "notifyToolkitThreadFree", "()V"); |
|
178 |
JNFCallStaticVoidMethod(env, jm_notifyFreeMethod); |
|
179 |
} |
|
180 |
} |
|
181 |
||
182 |
static void BusyObserver(CFRunLoopObserverRef ref, CFRunLoopActivity what, void* arg) { |
|
183 |
AWT_ASSERT_APPKIT_THREAD; |
|
184 |
||
185 |
// This is only called with the selector kCFRunLoopAfterWaiting. |
|
186 |
#ifndef PRODUCT_BUILD |
|
187 |
assert(what == kCFRunLoopAfterWaiting); |
|
188 |
#endif /* PRODUCT_BUILD */ |
|
189 |
||
190 |
setBusy(YES); |
|
191 |
} |
|
192 |
||
193 |
static void NotBusyObserver(CFRunLoopObserverRef ref, CFRunLoopActivity what, void* arg) { |
|
194 |
AWT_ASSERT_APPKIT_THREAD; |
|
195 |
||
196 |
// This is only called with the selector kCFRunLoopBeforeWaiting. |
|
197 |
#ifndef PRODUCT_BUILD |
|
198 |
assert(what == kCFRunLoopBeforeWaiting); |
|
199 |
#endif /* PRODUCT_BUILD */ |
|
200 |
||
201 |
setBusy(NO); |
|
202 |
} |
|
203 |
||
204 |
static void AWT_NSUncaughtExceptionHandler(NSException *exception) { |
|
205 |
NSLog(@"Apple AWT Internal Exception: %@", [exception description]); |
|
206 |
} |
|
207 |
||
208 |
// This is an empty Obj-C object just so that -peformSelectorOnMainThread can be used. |
|
209 |
@interface AWTStarter : NSObject { } |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
210 |
+ (void)start:(BOOL)headless; |
12047 | 211 |
- (void)starter:(NSArray*)args; |
212 |
+ (void)appKitIsRunning:(id)arg; |
|
213 |
@end |
|
214 |
||
215 |
@implementation AWTStarter |
|
216 |
||
217 |
+ (BOOL) isConnectedToWindowServer { |
|
218 |
SecuritySessionId session_id; |
|
219 |
SessionAttributeBits session_info; |
|
220 |
OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info); |
|
221 |
if (status != noErr) return NO; |
|
222 |
if (!(session_info & sessionHasGraphicAccess)) return NO; |
|
223 |
return YES; |
|
224 |
} |
|
225 |
||
226 |
+ (BOOL) markAppAsDaemon { |
|
227 |
id jrsAppKitAWTClass = objc_getClass("JRSAppKitAWT"); |
|
228 |
SEL markAppSel = @selector(markAppIsDaemon); |
|
229 |
if (![jrsAppKitAWTClass respondsToSelector:markAppSel]) return NO; |
|
20453
e480eb64d2c2
7174704: [macosx] New issue in 7u6 b12: HeadlessPrintingTest failure
anthony
parents:
17142
diff
changeset
|
230 |
return [jrsAppKitAWTClass performSelector:markAppSel] ? YES : NO; |
12047 | 231 |
} |
232 |
||
233 |
+ (void)appKitIsRunning:(id)arg { |
|
234 |
// Headless: NO |
|
235 |
// Embedded: BOTH |
|
236 |
// Multiple Calls: NO |
|
237 |
// Callers: AppKit's NSApplicationDidFinishLaunchingNotification or +[AWTStarter startAWT:] |
|
238 |
AWT_ASSERT_APPKIT_THREAD; |
|
239 |
||
240 |
BOOL verbose = ShouldPrintVerboseDebugging(); |
|
241 |
if (verbose) AWT_DEBUG_LOG(@"about to message AppKit started"); |
|
242 |
||
243 |
// Signal that AppKit has started (or is already running). |
|
244 |
pthread_mutex_lock(&sAppKitStarted_mutex); |
|
245 |
sAppKitStarted = YES; |
|
246 |
pthread_cond_signal(&sAppKitStarted_cv); |
|
247 |
pthread_mutex_unlock(&sAppKitStarted_mutex); |
|
248 |
||
249 |
if (verbose) AWT_DEBUG_LOG(@"finished messaging AppKit started"); |
|
250 |
} |
|
251 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
252 |
+ (void)start:(BOOL)headless |
12047 | 253 |
{ |
254 |
BOOL verbose = ShouldPrintVerboseDebugging(); |
|
255 |
||
256 |
// Headless: BOTH |
|
257 |
// Embedded: BOTH |
|
258 |
// Multiple Calls: NO |
|
259 |
// Caller: JNI_OnLoad |
|
260 |
||
261 |
// onMainThread is NOT the same at SWT mode! |
|
262 |
// If the JVM was started on the first thread for SWT, but the SWT loads the AWT on a secondary thread, |
|
263 |
// onMainThread here will be false but SWT mode will be true. If we are currently on the main thread, we don't |
|
264 |
// need to throw AWT startup over to another thread. |
|
265 |
BOOL onMainThread = (pthread_main_np() != 0); |
|
266 |
||
267 |
if (verbose) { |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
268 |
NSString *msg = [NSString stringWithFormat:@"+[AWTStarter start headless:%d] { onMainThread:%d }", headless, onMainThread]; |
12047 | 269 |
AWT_DEBUG_LOG(msg); |
270 |
} |
|
271 |
||
272 |
if (!headless) |
|
273 |
{ |
|
274 |
// Listen for the NSApp to start. This indicates that JNI_OnLoad can proceed. |
|
275 |
// It must wait because there is a chance that another java thread will grab |
|
276 |
// the AppKit lock before the +[NSApplication sharedApplication] returns. |
|
277 |
// See <rdar://problem/3492666> for an example. |
|
278 |
[[NSNotificationCenter defaultCenter] addObserver:[AWTStarter class] |
|
279 |
selector:@selector(appKitIsRunning:) |
|
280 |
name:NSApplicationDidFinishLaunchingNotification |
|
281 |
object:nil]; |
|
282 |
||
283 |
if (verbose) NSLog(@"+[AWTStarter start:::]: registered NSApplicationDidFinishLaunchingNotification"); |
|
284 |
} |
|
285 |
||
286 |
id st = [[AWTStarter alloc] init]; |
|
287 |
||
288 |
NSArray * args = [NSArray arrayWithObjects: |
|
289 |
[NSNumber numberWithBool: onMainThread], |
|
290 |
[NSNumber numberWithBool: headless], |
|
291 |
[NSNumber numberWithBool: verbose], |
|
292 |
nil]; |
|
293 |
||
294 |
if (onMainThread) { |
|
295 |
[st starter:args]; |
|
296 |
} else { |
|
297 |
[st performSelectorOnMainThread: @selector(starter:) withObject:args waitUntilDone:NO]; |
|
298 |
} |
|
299 |
||
300 |
if (!headless && !onMainThread) { |
|
301 |
if (verbose) AWT_DEBUG_LOG(@"about to wait on AppKit startup mutex"); |
|
302 |
||
303 |
// Wait here for AppKit to have started (or for AWT to have been loaded into |
|
304 |
// an already running NSApplication). |
|
305 |
pthread_mutex_lock(&sAppKitStarted_mutex); |
|
306 |
while (sAppKitStarted == NO) { |
|
307 |
pthread_cond_wait(&sAppKitStarted_cv, &sAppKitStarted_mutex); |
|
308 |
} |
|
309 |
pthread_mutex_unlock(&sAppKitStarted_mutex); |
|
310 |
||
311 |
// AWT gets here AFTER +[AWTStarter appKitIsRunning:] is called. |
|
312 |
if (verbose) AWT_DEBUG_LOG(@"got out of the AppKit startup mutex"); |
|
313 |
} |
|
12282
b057800f17c2
7132692: [macosx] Class com.apple.eawt not functioning
anthony
parents:
12047
diff
changeset
|
314 |
|
21241
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
315 |
if (!headless) { |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
316 |
// Don't set the delegate until the NSApplication has been created and |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
317 |
// its finishLaunching has initialized it. |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
318 |
// ApplicationDelegate is the support code for com.apple.eawt. |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
319 |
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){ |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
320 |
id<NSApplicationDelegate> delegate = [ApplicationDelegate sharedDelegate]; |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
321 |
if (delegate != nil) { |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
322 |
OSXAPP_SetApplicationDelegate(delegate); |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
323 |
} |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
324 |
}]; |
dc8cd488885d
7159266: [macosx] ApplicationDelegate should not be set in the headless mode
anthony
parents:
20453
diff
changeset
|
325 |
} |
12047 | 326 |
} |
327 |
||
328 |
- (void)starter:(NSArray*)args { |
|
329 |
NSAutoreleasePool *pool = [NSAutoreleasePool new]; |
|
330 |
||
331 |
BOOL onMainThread = [[args objectAtIndex:0] boolValue]; |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
332 |
BOOL headless = [[args objectAtIndex:1] boolValue]; |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
333 |
BOOL verbose = [[args objectAtIndex:2] boolValue]; |
12047 | 334 |
|
335 |
BOOL wasOnMainThread = onMainThread; |
|
336 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
337 |
// Add the exception handler of last resort |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
338 |
NSSetUncaughtExceptionHandler(AWT_NSUncaughtExceptionHandler); |
12047 | 339 |
|
340 |
// Headless mode trumps either ordinary AWT or SWT-in-AWT mode. Declare us a daemon and return. |
|
341 |
if (headless) { |
|
20453
e480eb64d2c2
7174704: [macosx] New issue in 7u6 b12: HeadlessPrintingTest failure
anthony
parents:
17142
diff
changeset
|
342 |
// Note that we don't install run loop observers in headless mode |
e480eb64d2c2
7174704: [macosx] New issue in 7u6 b12: HeadlessPrintingTest failure
anthony
parents:
17142
diff
changeset
|
343 |
// because we don't need them (see 7174704) |
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
344 |
if (!forceEmbeddedMode) { |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
345 |
setUpAppKitThreadName(); |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
346 |
} |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
347 |
[AWTStarter markAppAsDaemon]; |
12047 | 348 |
return; |
349 |
} |
|
350 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
351 |
if (forceEmbeddedMode) { |
12047 | 352 |
if (verbose) NSLog(@"in SWT or SWT/WebStart mode"); |
353 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
354 |
// Init a default NSApplication instance instead of the NSApplicationAWT. |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
355 |
// Note that [NSApp isRunning] will return YES after that, though |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
356 |
// this behavior isn't specified anywhere. We rely on that. |
12047 | 357 |
NSApplicationLoad(); |
358 |
} |
|
359 |
||
360 |
// This will create a NSApplicationAWT for standalone AWT programs, unless there is |
|
361 |
// already a NSApplication instance. If there is already a NSApplication instance, |
|
362 |
// and -[NSApplication isRunning] returns YES, AWT is embedded inside another |
|
363 |
// AppKit Application. |
|
364 |
NSApplication *app = [NSApplicationAWT sharedApplication]; |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
365 |
isEmbedded = ![NSApp isKindOfClass:[NSApplicationAWT class]]; |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
366 |
|
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
367 |
if (!isEmbedded) { |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
368 |
// Install run loop observers and set the AppKit Java thread name |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
369 |
setUpAWTAppKit(); |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
370 |
setUpAppKitThreadName(); |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
371 |
} |
12047 | 372 |
|
373 |
// AWT gets to this point BEFORE NSApplicationDidFinishLaunchingNotification is sent. |
|
374 |
if (![app isRunning]) { |
|
375 |
if (verbose) AWT_DEBUG_LOG(@"+[AWTStarter startAWT]: ![app isRunning]"); |
|
376 |
||
377 |
// This is where the AWT AppKit thread parks itself to process events. |
|
378 |
[NSApplicationAWT runAWTLoopWithApp: app]; |
|
379 |
} else { |
|
380 |
// We're either embedded, or showing a splash screen |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
381 |
if (isEmbedded) { |
12047 | 382 |
if (verbose) AWT_DEBUG_LOG(@"running embedded"); |
383 |
||
14753
a56a685d137f
7154778: [macosx] NSView-based implementation of sun.awt.EmbeddedFrame
serb
parents:
12282
diff
changeset
|
384 |
// We don't track if the runloop is busy, so set it free to let AWT finish when it needs |
a56a685d137f
7154778: [macosx] NSView-based implementation of sun.awt.EmbeddedFrame
serb
parents:
12282
diff
changeset
|
385 |
setBusy(NO); |
12047 | 386 |
} else { |
387 |
if (verbose) AWT_DEBUG_LOG(@"running after showing a splash screen"); |
|
388 |
} |
|
389 |
||
390 |
// Signal so that JNI_OnLoad can proceed. |
|
391 |
if (!wasOnMainThread) [AWTStarter appKitIsRunning:nil]; |
|
392 |
||
393 |
// Proceed to exit this call as there is no reason to run the NSApplication event loop. |
|
394 |
} |
|
395 |
||
396 |
[pool drain]; |
|
397 |
} |
|
398 |
||
399 |
@end |
|
400 |
||
401 |
||
402 |
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { |
|
403 |
BOOL verbose = ShouldPrintVerboseDebugging(); |
|
404 |
if (verbose) AWT_DEBUG_LOG(@"entered JNI_OnLoad"); |
|
405 |
||
406 |
// Headless: BOTH |
|
407 |
// Embedded: BOTH |
|
408 |
// Multiple Calls: NO |
|
409 |
// Caller: JavaVM classloader |
|
410 |
||
411 |
// Keep a static reference for other archives. |
|
412 |
OSXAPP_SetJavaVM(vm); |
|
413 |
||
414 |
JNIEnv *env = NULL; |
|
415 |
||
416 |
// Need JNIEnv for JNF_COCOA_ENTER(env); macro below |
|
417 |
jint status = (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4); |
|
418 |
if (status != JNI_OK || env == NULL) { |
|
419 |
AWT_DEBUG_LOG(@"Can't get JNIEnv"); |
|
420 |
return JNI_VERSION_1_4; |
|
421 |
} |
|
422 |
||
423 |
JNF_COCOA_ENTER(env); |
|
424 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
425 |
// Launcher sets this env variable if -XstartOnFirstThread is specified |
12047 | 426 |
char envVar[80]; |
427 |
snprintf(envVar, sizeof(envVar), "JAVA_STARTED_ON_FIRST_THREAD_%d", getpid()); |
|
428 |
if (getenv(envVar) != NULL) { |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
429 |
forceEmbeddedMode = YES; |
12047 | 430 |
unsetenv(envVar); |
431 |
} |
|
432 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
433 |
if (isSWTInWebStart(env)) { |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
434 |
forceEmbeddedMode = YES; |
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
435 |
} |
12047 | 436 |
|
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
437 |
BOOL headless = isHeadless(env); |
12047 | 438 |
|
439 |
// We need to let Foundation know that this is a multithreaded application, if it isn't already. |
|
440 |
if (![NSThread isMultiThreaded]) { |
|
441 |
[NSThread detachNewThreadSelector:nil toTarget:nil withObject:nil]; |
|
442 |
} |
|
443 |
||
15321
da912a45f4e6
8005465: [macosx] Evaluate if checking for the -XstartOnFirstThread is still needed in awt.m
anthony
parents:
14753
diff
changeset
|
444 |
[AWTStarter start:headless]; |
12047 | 445 |
|
446 |
JNF_COCOA_EXIT(env); |
|
447 |
||
448 |
if (verbose) AWT_DEBUG_LOG(@"exiting JNI_OnLoad"); |
|
449 |
||
450 |
return JNI_VERSION_1_4; |
|
451 |
} |