Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/native_NOTIOS/sun/osxapp/NSApplicationAWT.m
38829 views
1
/*
2
* Copyright (c) 2011, 2016, 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 "NSApplicationAWT.h"
27
28
#import <objc/runtime.h>
29
#import <JavaRuntimeSupport/JavaRuntimeSupport.h>
30
31
#import "PropertiesUtilities.h"
32
#import "ThreadUtilities.h"
33
#import "QueuingApplicationDelegate.h"
34
#import "AWTIconData.h"
35
36
37
static BOOL sUsingDefaultNIB = YES;
38
static NSString *SHARED_FRAMEWORK_BUNDLE = @"/System/Library/Frameworks/JavaVM.framework";
39
static id <NSApplicationDelegate> applicationDelegate = nil;
40
static QueuingApplicationDelegate * qad = nil;
41
42
// Flag used to indicate to the Plugin2 event synthesis code to do a postEvent instead of sendEvent
43
BOOL postEventDuringEventSynthesis = NO;
44
45
@implementation NSApplicationAWT
46
47
- (id) init
48
{
49
// Headless: NO
50
// Embedded: NO
51
// Multiple Calls: NO
52
// Caller: +[NSApplication sharedApplication]
53
54
AWT_ASSERT_APPKIT_THREAD;
55
fApplicationName = nil;
56
dummyEventTimestamp = 0.0;
57
seenDummyEventLock = nil;
58
59
60
// NSApplication will call _RegisterApplication with the application's bundle, but there may not be one.
61
// So, we need to call it ourselves to ensure the app is set up properly.
62
[self registerWithProcessManager];
63
64
return [super init];
65
}
66
67
- (void)dealloc
68
{
69
[fApplicationName release];
70
fApplicationName = nil;
71
72
[super dealloc];
73
}
74
75
- (void)finishLaunching
76
{
77
AWT_ASSERT_APPKIT_THREAD;
78
79
JNIEnv *env = [ThreadUtilities getJNIEnv];
80
81
// Get default nib file location
82
// NOTE: This should learn about the current java.version. Probably best thru
83
// the Makefile system's -DFRAMEWORK_VERSION define. Need to be able to pass this
84
// thru to PB from the Makefile system and for local builds.
85
NSString *defaultNibFile = [PropertiesUtilities javaSystemPropertyForKey:@"apple.awt.application.nib" withEnv:env];
86
if (!defaultNibFile) {
87
NSBundle *javaBundle = [NSBundle bundleWithPath:SHARED_FRAMEWORK_BUNDLE];
88
defaultNibFile = [javaBundle pathForResource:@"DefaultApp" ofType:@"nib"];
89
} else {
90
sUsingDefaultNIB = NO;
91
}
92
93
[NSBundle loadNibFile:defaultNibFile externalNameTable: [NSDictionary dictionaryWithObject:self forKey:@"NSOwner"] withZone:nil];
94
95
// Set user defaults to not try to parse application arguments.
96
NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
97
NSDictionary * noOpenDict = [NSDictionary dictionaryWithObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
98
[defs registerDefaults:noOpenDict];
99
100
// Fix up the dock icon now that we are registered with CAS and the Dock.
101
[self setDockIconWithEnv:env];
102
103
// If we are using our nib (the default application NIB) we need to put the app name into
104
// the application menu, which has placeholders for the name.
105
if (sUsingDefaultNIB) {
106
NSUInteger i, itemCount;
107
NSMenu *theMainMenu = [NSApp mainMenu];
108
109
// First submenu off the main menu is the application menu.
110
NSMenuItem *appMenuItem = [theMainMenu itemAtIndex:0];
111
NSMenu *appMenu = [appMenuItem submenu];
112
itemCount = [appMenu numberOfItems];
113
114
for (i = 0; i < itemCount; i++) {
115
NSMenuItem *anItem = [appMenu itemAtIndex:i];
116
NSString *oldTitle = [anItem title];
117
[anItem setTitle:[NSString stringWithFormat:oldTitle, fApplicationName]];
118
}
119
}
120
121
if (applicationDelegate) {
122
[self setDelegate:applicationDelegate];
123
} else {
124
qad = [QueuingApplicationDelegate sharedDelegate];
125
[self setDelegate:qad];
126
}
127
128
[super finishLaunching];
129
130
// inform any interested parties that the AWT has arrived and is pumping
131
[[NSNotificationCenter defaultCenter] postNotificationName:JNFRunLoopDidStartNotification object:self];
132
}
133
134
- (void) registerWithProcessManager
135
{
136
// Headless: NO
137
// Embedded: NO
138
// Multiple Calls: NO
139
// Caller: -[NSApplicationAWT init]
140
141
AWT_ASSERT_APPKIT_THREAD;
142
JNIEnv *env = [ThreadUtilities getJNIEnv];
143
144
char envVar[80];
145
146
// The following environment variable is set from the -Xdock:name param. It should be UTF8.
147
snprintf(envVar, sizeof(envVar), "APP_NAME_%d", getpid());
148
char *appName = getenv(envVar);
149
if (appName != NULL) {
150
fApplicationName = [NSString stringWithUTF8String:appName];
151
unsetenv(envVar);
152
}
153
154
// If it wasn't specified as an argument, see if it was specified as a system property.
155
if (fApplicationName == nil) {
156
fApplicationName = [PropertiesUtilities javaSystemPropertyForKey:@"apple.awt.application.name" withEnv:env];
157
}
158
159
// If we STILL don't have it, the app name is retrieved from an environment variable (set in java.c) It should be UTF8.
160
if (fApplicationName == nil) {
161
char mainClassEnvVar[80];
162
snprintf(mainClassEnvVar, sizeof(mainClassEnvVar), "JAVA_MAIN_CLASS_%d", getpid());
163
char *mainClass = getenv(mainClassEnvVar);
164
if (mainClass != NULL) {
165
fApplicationName = [NSString stringWithUTF8String:mainClass];
166
unsetenv(mainClassEnvVar);
167
168
NSRange lastPeriod = [fApplicationName rangeOfString:@"." options:NSBackwardsSearch];
169
if (lastPeriod.location != NSNotFound) {
170
fApplicationName = [fApplicationName substringFromIndex:lastPeriod.location + 1];
171
}
172
}
173
}
174
175
// The dock name is nil for double-clickable Java apps (bundled and Web Start apps)
176
// When that happens get the display name, and if that's not available fall back to
177
// CFBundleName.
178
NSBundle *mainBundle = [NSBundle mainBundle];
179
if (fApplicationName == nil) {
180
fApplicationName = (NSString *)[mainBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"];
181
182
if (fApplicationName == nil) {
183
fApplicationName = (NSString *)[mainBundle objectForInfoDictionaryKey:(NSString *)kCFBundleNameKey];
184
185
if (fApplicationName == nil) {
186
fApplicationName = (NSString *)[mainBundle objectForInfoDictionaryKey: (NSString *)kCFBundleExecutableKey];
187
188
if (fApplicationName == nil) {
189
// Name of last resort is the last part of the applicatoin name without the .app (consistent with CopyProcessName)
190
fApplicationName = [[mainBundle bundlePath] lastPathComponent];
191
192
if ([fApplicationName hasSuffix:@".app"]) {
193
fApplicationName = [fApplicationName stringByDeletingPathExtension];
194
}
195
}
196
}
197
}
198
}
199
200
// We're all done trying to determine the app name. Hold on to it.
201
[fApplicationName retain];
202
203
NSDictionary *registrationOptions = [NSMutableDictionary dictionaryWithObject:fApplicationName forKey:@"JRSAppNameKey"];
204
205
NSString *launcherType = [PropertiesUtilities javaSystemPropertyForKey:@"sun.java.launcher" withEnv:env];
206
if ([@"SUN_STANDARD" isEqualToString:launcherType]) {
207
[registrationOptions setValue:[NSNumber numberWithBool:YES] forKey:@"JRSAppIsCommandLineKey"];
208
}
209
210
NSString *uiElementProp = [PropertiesUtilities javaSystemPropertyForKey:@"apple.awt.UIElement" withEnv:env];
211
if ([@"true" isCaseInsensitiveLike:uiElementProp]) {
212
[registrationOptions setValue:[NSNumber numberWithBool:YES] forKey:@"JRSAppIsUIElementKey"];
213
}
214
215
NSString *backgroundOnlyProp = [PropertiesUtilities javaSystemPropertyForKey:@"apple.awt.BackgroundOnly" withEnv:env];
216
if ([@"true" isCaseInsensitiveLike:backgroundOnlyProp]) {
217
[registrationOptions setValue:[NSNumber numberWithBool:YES] forKey:@"JRSAppIsBackgroundOnlyKey"];
218
}
219
220
// TODO replace with direct call
221
// [JRSAppKitAWT registerAWTAppWithOptions:registrationOptions];
222
// and remove below transform/activate/run hack
223
224
id jrsAppKitAWTClass = objc_getClass("JRSAppKitAWT");
225
SEL registerSel = @selector(registerAWTAppWithOptions:);
226
if ([jrsAppKitAWTClass respondsToSelector:registerSel]) {
227
[jrsAppKitAWTClass performSelector:registerSel withObject:registrationOptions];
228
return;
229
}
230
231
// HACK BEGIN
232
// The following is necessary to make the java process behave like a
233
// proper foreground application...
234
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
235
ProcessSerialNumber psn;
236
GetCurrentProcess(&psn);
237
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
238
239
[NSApp activateIgnoringOtherApps:YES];
240
[NSApp run];
241
}];
242
// HACK END
243
}
244
245
- (void) setDockIconWithEnv:(JNIEnv *)env {
246
NSString *theIconPath = nil;
247
248
// The following environment variable is set in java.c. It is probably UTF8.
249
char envVar[80];
250
snprintf(envVar, sizeof(envVar), "APP_ICON_%d", getpid());
251
char *appIcon = getenv(envVar);
252
if (appIcon != NULL) {
253
theIconPath = [NSString stringWithUTF8String:appIcon];
254
unsetenv(envVar);
255
}
256
257
if (theIconPath == nil) {
258
theIconPath = [PropertiesUtilities javaSystemPropertyForKey:@"apple.awt.application.icon" withEnv:env];
259
}
260
261
// Use the path specified to get the icon image
262
NSImage* iconImage = nil;
263
if (theIconPath != nil) {
264
iconImage = [[NSImage alloc] initWithContentsOfFile:theIconPath];
265
}
266
267
// If no icon file was specified or we failed to get the icon image
268
// and there is no bundle's icon, then use the default icon
269
if (iconImage == nil) {
270
NSString* bundleIcon = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIconFile"];
271
if (bundleIcon == nil) {
272
NSData* iconData;
273
iconData = [[NSData alloc] initWithBytesNoCopy: sAWTIconData length: sizeof(sAWTIconData) freeWhenDone: NO];
274
iconImage = [[NSImage alloc] initWithData: iconData];
275
[iconData release];
276
}
277
}
278
279
// Set up the dock icon if we have an icon image.
280
if (iconImage != nil) {
281
[NSApp setApplicationIconImage:iconImage];
282
[iconImage release];
283
}
284
}
285
286
+ (void) runAWTLoopWithApp:(NSApplication*)app {
287
NSAutoreleasePool *pool = [NSAutoreleasePool new];
288
289
// Make sure that when we run in AWTRunLoopMode we don't exit randomly
290
[[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:[JNFRunLoop javaRunLoopMode]];
291
292
do {
293
@try {
294
[app run];
295
} @catch (NSException* e) {
296
NSLog(@"Apple AWT Startup Exception: %@", [e description]);
297
NSLog(@"Apple AWT Restarting Native Event Thread");
298
299
[app stop:app];
300
}
301
} while (YES);
302
303
[pool drain];
304
}
305
306
- (BOOL)usingDefaultNib {
307
return sUsingDefaultNIB;
308
}
309
310
- (void)orderFrontStandardAboutPanelWithOptions:(NSDictionary *)optionsDictionary {
311
if (!optionsDictionary) {
312
optionsDictionary = [NSMutableDictionary dictionaryWithCapacity:2];
313
[optionsDictionary setValue:[[[[[NSApp mainMenu] itemAtIndex:0] submenu] itemAtIndex:0] title] forKey:@"ApplicationName"];
314
if (![NSImage imageNamed:@"NSApplicationIcon"]) {
315
[optionsDictionary setValue:[NSApp applicationIconImage] forKey:@"ApplicationIcon"];
316
}
317
}
318
319
[super orderFrontStandardAboutPanelWithOptions:optionsDictionary];
320
}
321
322
#define DRAGMASK (NSMouseMovedMask | NSLeftMouseDraggedMask | NSRightMouseDownMask | NSRightMouseDraggedMask | NSLeftMouseUpMask | NSRightMouseUpMask | NSFlagsChangedMask | NSKeyDownMask)
323
324
- (NSEvent *)nextEventMatchingMask:(NSUInteger)mask untilDate:(NSDate *)expiration inMode:(NSString *)mode dequeue:(BOOL)deqFlag {
325
if (mask == DRAGMASK && [((NSString *)kCFRunLoopDefaultMode) isEqual:mode]) {
326
postEventDuringEventSynthesis = YES;
327
}
328
329
NSEvent *event = [super nextEventMatchingMask:mask untilDate:expiration inMode:mode dequeue: deqFlag];
330
postEventDuringEventSynthesis = NO;
331
332
return event;
333
}
334
335
// NSTimeInterval has microseconds precision
336
#define TS_EQUAL(ts1, ts2) (fabs((ts1) - (ts2)) < 1e-6)
337
338
- (void)sendEvent:(NSEvent *)event
339
{
340
if ([event type] == NSApplicationDefined && TS_EQUAL([event timestamp], dummyEventTimestamp) && [event subtype] == 0) {
341
[seenDummyEventLock lockWhenCondition:NO];
342
[seenDummyEventLock unlockWithCondition:YES];
343
} else if ([event type] == NSApplicationDefined && [event subtype] == 777) {
344
void (^block)() = (void (^)()) [event data1];
345
block();
346
[block release];
347
} else if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask)) {
348
// Cocoa won't send us key up event when releasing a key while Cmd is down,
349
// so we have to do it ourselves.
350
[[self keyWindow] sendEvent:event];
351
} else {
352
[super sendEvent:event];
353
}
354
}
355
356
/*
357
* Posts the block to the AppKit event queue which will be executed
358
* on the main AppKit loop.
359
* While running nested loops this event will be ignored.
360
*/
361
- (void)postRunnableEvent:(void (^)())block
362
{
363
void (^copy)() = [block copy];
364
NSInteger encode = (NSInteger) copy;
365
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
366
NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined
367
location: NSMakePoint(0,0)
368
modifierFlags: 0
369
timestamp: 0
370
windowNumber: 0
371
context: nil
372
subtype: 777
373
data1: encode
374
data2: 0];
375
376
[NSApp postEvent: event atStart: NO];
377
[pool drain];
378
}
379
380
- (void)postDummyEvent:(bool)useCocoa {
381
seenDummyEventLock = [[NSConditionLock alloc] initWithCondition:NO];
382
dummyEventTimestamp = [NSProcessInfo processInfo].systemUptime;
383
384
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
385
NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined
386
location: NSMakePoint(0,0)
387
modifierFlags: 0
388
timestamp: dummyEventTimestamp
389
windowNumber: 0
390
context: nil
391
subtype: 0
392
data1: 0
393
data2: 0];
394
if (useCocoa) {
395
[NSApp postEvent:event atStart:NO];
396
} else {
397
ProcessSerialNumber psn;
398
GetCurrentProcess(&psn);
399
CGEventPostToPSN(&psn, [event CGEvent]);
400
}
401
[pool drain];
402
}
403
404
- (void)waitForDummyEvent:(double)timeout {
405
bool unlock = true;
406
if (timeout >= 0) {
407
double sec = timeout / 1000;
408
unlock = [seenDummyEventLock lockWhenCondition:YES
409
beforeDate:[NSDate dateWithTimeIntervalSinceNow:sec]];
410
} else {
411
[seenDummyEventLock lockWhenCondition:YES];
412
}
413
if (unlock) {
414
[seenDummyEventLock unlock];
415
}
416
[seenDummyEventLock release];
417
418
seenDummyEventLock = nil;
419
}
420
421
@end
422
423
424
void OSXAPP_SetApplicationDelegate(id <NSApplicationDelegate> delegate)
425
{
426
AWT_ASSERT_APPKIT_THREAD;
427
applicationDelegate = delegate;
428
429
if (NSApp != nil) {
430
[NSApp setDelegate: applicationDelegate];
431
432
if (applicationDelegate && qad) {
433
[qad processQueuedEventsWithTargetDelegate: applicationDelegate];
434
qad = nil;
435
}
436
}
437
}
438
439
440