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/classes/com/apple/eawt/_AppEventHandler.java
38831 views
1
/*
2
* Copyright (c) 2011, 2013, 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
package com.apple.eawt;
27
28
import java.awt.*;
29
import java.awt.event.WindowEvent;
30
import java.io.File;
31
import java.net.*;
32
import java.util.*;
33
import java.util.List;
34
import sun.awt.AppContext;
35
import sun.awt.SunToolkit;
36
37
import com.apple.eawt.AppEvent.*;
38
39
class _AppEventHandler {
40
private static final int NOTIFY_ABOUT = 1;
41
private static final int NOTIFY_PREFS = 2;
42
private static final int NOTIFY_OPEN_APP = 3;
43
private static final int NOTIFY_REOPEN_APP = 4;
44
private static final int NOTIFY_QUIT = 5;
45
private static final int NOTIFY_SHUTDOWN = 6;
46
private static final int NOTIFY_ACTIVE_APP_GAINED = 7;
47
private static final int NOTIFY_ACTIVE_APP_LOST = 8;
48
private static final int NOTIFY_APP_HIDDEN = 9;
49
private static final int NOTIFY_APP_SHOWN = 10;
50
private static final int NOTIFY_USER_SESSION_ACTIVE = 11;
51
private static final int NOTIFY_USER_SESSION_INACTIVE = 12;
52
private static final int NOTIFY_SCREEN_SLEEP = 13;
53
private static final int NOTIFY_SCREEN_WAKE = 14;
54
private static final int NOTIFY_SYSTEM_SLEEP = 15;
55
private static final int NOTIFY_SYSTEM_WAKE = 16;
56
57
private static final int REGISTER_USER_SESSION = 1;
58
private static final int REGISTER_SCREEN_SLEEP = 2;
59
private static final int REGISTER_SYSTEM_SLEEP = 3;
60
61
private static native void nativeOpenCocoaAboutWindow();
62
private static native void nativeReplyToAppShouldTerminate(final boolean shouldTerminate);
63
private static native void nativeRegisterForNotification(final int notification);
64
65
final static _AppEventHandler instance = new _AppEventHandler();
66
static _AppEventHandler getInstance() {
67
return instance;
68
}
69
70
// single shot dispatchers (some queuing, others not)
71
final _AboutDispatcher aboutDispatcher = new _AboutDispatcher();
72
final _PreferencesDispatcher preferencesDispatcher = new _PreferencesDispatcher();
73
final _OpenFileDispatcher openFilesDispatcher = new _OpenFileDispatcher();
74
final _PrintFileDispatcher printFilesDispatcher = new _PrintFileDispatcher();
75
final _OpenURIDispatcher openURIDispatcher = new _OpenURIDispatcher();
76
final _QuitDispatcher quitDispatcher = new _QuitDispatcher();
77
final _OpenAppDispatcher openAppDispatcher = new _OpenAppDispatcher();
78
79
// multiplexing dispatchers (contains listener lists)
80
final _AppReOpenedDispatcher reOpenAppDispatcher = new _AppReOpenedDispatcher();
81
final _AppForegroundDispatcher foregroundAppDispatcher = new _AppForegroundDispatcher();
82
final _HiddenAppDispatcher hiddenAppDispatcher = new _HiddenAppDispatcher();
83
final _UserSessionDispatcher userSessionDispatcher = new _UserSessionDispatcher();
84
final _ScreenSleepDispatcher screenSleepDispatcher = new _ScreenSleepDispatcher();
85
final _SystemSleepDispatcher systemSleepDispatcher = new _SystemSleepDispatcher();
86
87
final _AppEventLegacyHandler legacyHandler = new _AppEventLegacyHandler(this);
88
89
QuitStrategy defaultQuitAction = QuitStrategy.SYSTEM_EXIT_0;
90
91
_AppEventHandler() {
92
final String strategyProp = System.getProperty("apple.eawt.quitStrategy");
93
if (strategyProp == null) return;
94
95
if ("CLOSE_ALL_WINDOWS".equals(strategyProp)) {
96
setDefaultQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);
97
} else if ("SYSTEM_EXIT_O".equals(strategyProp)) {
98
setDefaultQuitStrategy(QuitStrategy.SYSTEM_EXIT_0);
99
} else {
100
System.err.println("unrecognized apple.eawt.quitStrategy: " + strategyProp);
101
}
102
}
103
104
void addListener(final AppEventListener listener) {
105
if (listener instanceof AppReOpenedListener) reOpenAppDispatcher.addListener((AppReOpenedListener)listener);
106
if (listener instanceof AppForegroundListener) foregroundAppDispatcher.addListener((AppForegroundListener)listener);
107
if (listener instanceof AppHiddenListener) hiddenAppDispatcher.addListener((AppHiddenListener)listener);
108
if (listener instanceof UserSessionListener) userSessionDispatcher.addListener((UserSessionListener)listener);
109
if (listener instanceof ScreenSleepListener) screenSleepDispatcher.addListener((ScreenSleepListener)listener);
110
if (listener instanceof SystemSleepListener) systemSleepDispatcher.addListener((SystemSleepListener)listener);
111
}
112
113
void removeListener(final AppEventListener listener) {
114
if (listener instanceof AppReOpenedListener) reOpenAppDispatcher.removeListener((AppReOpenedListener)listener);
115
if (listener instanceof AppForegroundListener) foregroundAppDispatcher.removeListener((AppForegroundListener)listener);
116
if (listener instanceof AppHiddenListener) hiddenAppDispatcher.removeListener((AppHiddenListener)listener);
117
if (listener instanceof UserSessionListener) userSessionDispatcher.removeListener((UserSessionListener)listener);
118
if (listener instanceof ScreenSleepListener) screenSleepDispatcher.removeListener((ScreenSleepListener)listener);
119
if (listener instanceof SystemSleepListener) systemSleepDispatcher.removeListener((SystemSleepListener)listener);
120
}
121
122
void openCocoaAboutWindow() {
123
nativeOpenCocoaAboutWindow();
124
}
125
126
void setDefaultQuitStrategy(final QuitStrategy defaultQuitAction) {
127
this.defaultQuitAction = defaultQuitAction;
128
}
129
130
QuitResponse currentQuitResponse;
131
synchronized QuitResponse obtainQuitResponse() {
132
if (currentQuitResponse != null) return currentQuitResponse;
133
return currentQuitResponse = new QuitResponse(this);
134
}
135
136
synchronized void cancelQuit() {
137
currentQuitResponse = null;
138
nativeReplyToAppShouldTerminate(false);
139
}
140
141
synchronized void performQuit() {
142
currentQuitResponse = null;
143
144
try {
145
if (defaultQuitAction == QuitStrategy.SYSTEM_EXIT_0) System.exit(0);
146
147
if (defaultQuitAction != QuitStrategy.CLOSE_ALL_WINDOWS) {
148
throw new RuntimeException("Unknown quit action");
149
}
150
151
EventQueue.invokeLater(new Runnable() {
152
public void run() {
153
// walk frames from back to front
154
final Frame[] allFrames = Frame.getFrames();
155
for (int i = allFrames.length - 1; i >= 0; i--) {
156
final Frame frame = allFrames[i];
157
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
158
}
159
}
160
});
161
} finally {
162
// Either we've just called System.exit(), or the app will call
163
// it when processing a WINDOW_CLOSING event. Either way, we reply
164
// to Cocoa that we don't want to exit the event loop yet.
165
nativeReplyToAppShouldTerminate(false);
166
}
167
}
168
169
/*
170
* callbacks from native delegate
171
*/
172
private static void handlePrintFiles(final List<String> filenames) {
173
instance.printFilesDispatcher.dispatch(new _NativeEvent(filenames));
174
}
175
176
private static void handleOpenFiles(final List<String> filenames, final String searchTerm) {
177
instance.openFilesDispatcher.dispatch(new _NativeEvent(filenames, searchTerm));
178
}
179
180
private static void handleOpenURI(final String uri) {
181
instance.openURIDispatcher.dispatch(new _NativeEvent(uri));
182
}
183
184
// default funnel for non-complex events
185
private static void handleNativeNotification(final int code) {
186
// System.out.println(code);
187
188
switch (code) {
189
case NOTIFY_ABOUT:
190
instance.aboutDispatcher.dispatch(new _NativeEvent());
191
break;
192
case NOTIFY_PREFS:
193
instance.preferencesDispatcher.dispatch(new _NativeEvent());
194
break;
195
case NOTIFY_OPEN_APP:
196
instance.openAppDispatcher.dispatch(new _NativeEvent());
197
break;
198
case NOTIFY_REOPEN_APP:
199
instance.reOpenAppDispatcher.dispatch(new _NativeEvent());
200
break;
201
case NOTIFY_QUIT:
202
instance.quitDispatcher.dispatch(new _NativeEvent());
203
break;
204
case NOTIFY_SHUTDOWN:
205
// do nothing for now
206
break;
207
case NOTIFY_ACTIVE_APP_GAINED:
208
instance.foregroundAppDispatcher.dispatch(new _NativeEvent(Boolean.TRUE));
209
break;
210
case NOTIFY_ACTIVE_APP_LOST:
211
instance.foregroundAppDispatcher.dispatch(new _NativeEvent(Boolean.FALSE));
212
break;
213
case NOTIFY_APP_HIDDEN:
214
instance.hiddenAppDispatcher.dispatch(new _NativeEvent(Boolean.TRUE));
215
break;
216
case NOTIFY_APP_SHOWN:
217
instance.hiddenAppDispatcher.dispatch(new _NativeEvent(Boolean.FALSE));
218
break;
219
case NOTIFY_USER_SESSION_ACTIVE:
220
instance.userSessionDispatcher.dispatch(new _NativeEvent(Boolean.TRUE));
221
break;
222
case NOTIFY_USER_SESSION_INACTIVE:
223
instance.userSessionDispatcher.dispatch(new _NativeEvent(Boolean.FALSE));
224
break;
225
case NOTIFY_SCREEN_SLEEP:
226
instance.screenSleepDispatcher.dispatch(new _NativeEvent(Boolean.TRUE));
227
break;
228
case NOTIFY_SCREEN_WAKE:
229
instance.screenSleepDispatcher.dispatch(new _NativeEvent(Boolean.FALSE));
230
break;
231
case NOTIFY_SYSTEM_SLEEP:
232
instance.systemSleepDispatcher.dispatch(new _NativeEvent(Boolean.TRUE));
233
break;
234
case NOTIFY_SYSTEM_WAKE:
235
instance.systemSleepDispatcher.dispatch(new _NativeEvent(Boolean.FALSE));
236
break;
237
default:
238
System.err.println("EAWT unknown native notification: " + code);
239
break;
240
}
241
}
242
243
244
class _AboutDispatcher extends _AppEventDispatcher<AboutHandler> {
245
void performDefaultAction(final _NativeEvent event) {
246
openCocoaAboutWindow(); // if the handler is null, fall back to showing the Cocoa default
247
}
248
249
void performUsing(final AboutHandler handler, final _NativeEvent event) {
250
handler.handleAbout(new AboutEvent());
251
}
252
}
253
254
class _PreferencesDispatcher extends _AppEventDispatcher<PreferencesHandler> {
255
synchronized void setHandler(final PreferencesHandler handler) {
256
super.setHandler(handler);
257
258
_AppMenuBarHandler.getInstance().setPreferencesMenuItemVisible(handler != null);
259
_AppMenuBarHandler.getInstance().setPreferencesMenuItemEnabled(handler != null);
260
}
261
262
void performUsing(final PreferencesHandler handler, final _NativeEvent event) {
263
handler.handlePreferences(new PreferencesEvent());
264
}
265
}
266
267
class _OpenAppDispatcher extends _QueuingAppEventDispatcher<com.apple.eawt._OpenAppHandler> {
268
void performUsing(com.apple.eawt._OpenAppHandler handler, _NativeEvent event) {
269
handler.handleOpenApp();
270
}
271
}
272
273
class _AppReOpenedDispatcher extends _AppEventMultiplexor<AppReOpenedListener> {
274
void performOnListener(AppReOpenedListener listener, final _NativeEvent event) {
275
final AppReOpenedEvent e = new AppReOpenedEvent();
276
listener.appReOpened(e);
277
}
278
}
279
280
class _AppForegroundDispatcher extends _BooleanAppEventMultiplexor<AppForegroundListener, AppForegroundEvent> {
281
AppForegroundEvent createEvent(final boolean isTrue) { return new AppForegroundEvent(); }
282
283
void performFalseEventOn(final AppForegroundListener listener, final AppForegroundEvent e) {
284
listener.appMovedToBackground(e);
285
}
286
287
void performTrueEventOn(final AppForegroundListener listener, final AppForegroundEvent e) {
288
listener.appRaisedToForeground(e);
289
}
290
}
291
292
class _HiddenAppDispatcher extends _BooleanAppEventMultiplexor<AppHiddenListener, AppHiddenEvent> {
293
AppHiddenEvent createEvent(final boolean isTrue) { return new AppHiddenEvent(); }
294
295
void performFalseEventOn(final AppHiddenListener listener, final AppHiddenEvent e) {
296
listener.appUnhidden(e);
297
}
298
299
void performTrueEventOn(final AppHiddenListener listener, final AppHiddenEvent e) {
300
listener.appHidden(e);
301
}
302
}
303
304
class _UserSessionDispatcher extends _BooleanAppEventMultiplexor<UserSessionListener, UserSessionEvent> {
305
UserSessionEvent createEvent(final boolean isTrue) { return new UserSessionEvent(); }
306
307
void performFalseEventOn(final UserSessionListener listener, final UserSessionEvent e) {
308
listener.userSessionDeactivated(e);
309
}
310
311
void performTrueEventOn(final UserSessionListener listener, final UserSessionEvent e) {
312
listener.userSessionActivated(e);
313
}
314
315
void registerNativeListener() {
316
nativeRegisterForNotification(REGISTER_USER_SESSION);
317
}
318
}
319
320
class _ScreenSleepDispatcher extends _BooleanAppEventMultiplexor<ScreenSleepListener, ScreenSleepEvent> {
321
ScreenSleepEvent createEvent(final boolean isTrue) { return new ScreenSleepEvent(); }
322
323
void performFalseEventOn(final ScreenSleepListener listener, final ScreenSleepEvent e) {
324
listener.screenAwoke(e);
325
}
326
327
void performTrueEventOn(final ScreenSleepListener listener, final ScreenSleepEvent e) {
328
listener.screenAboutToSleep(e);
329
}
330
331
void registerNativeListener() {
332
nativeRegisterForNotification(REGISTER_SCREEN_SLEEP);
333
}
334
}
335
336
class _SystemSleepDispatcher extends _BooleanAppEventMultiplexor<SystemSleepListener, SystemSleepEvent> {
337
SystemSleepEvent createEvent(final boolean isTrue) { return new SystemSleepEvent(); }
338
339
void performFalseEventOn(final SystemSleepListener listener, final SystemSleepEvent e) {
340
listener.systemAwoke(e);
341
}
342
343
void performTrueEventOn(final SystemSleepListener listener, final SystemSleepEvent e) {
344
listener.systemAboutToSleep(e);
345
}
346
347
void registerNativeListener() {
348
nativeRegisterForNotification(REGISTER_SYSTEM_SLEEP);
349
}
350
}
351
352
class _OpenFileDispatcher extends _QueuingAppEventDispatcher<OpenFilesHandler> {
353
void performUsing(final OpenFilesHandler handler, final _NativeEvent event) {
354
// create file list from fileNames
355
final List<String> fileNameList = event.get(0);
356
final ArrayList<File> files = new ArrayList<File>(fileNameList.size());
357
for (final String fileName : fileNameList) files.add(new File(fileName));
358
359
// populate the properties map
360
final String searchTerm = event.get(1);
361
handler.openFiles(new OpenFilesEvent(files, searchTerm));
362
}
363
}
364
365
class _PrintFileDispatcher extends _QueuingAppEventDispatcher<PrintFilesHandler> {
366
void performUsing(final PrintFilesHandler handler, final _NativeEvent event) {
367
// create file list from fileNames
368
final List<String> fileNameList = event.get(0);
369
final ArrayList<File> files = new ArrayList<File>(fileNameList.size());
370
for (final String fileName : fileNameList) files.add(new File(fileName));
371
372
handler.printFiles(new PrintFilesEvent(files));
373
}
374
}
375
376
// Java URLs can't handle unknown protocol types, which is why we use URIs
377
class _OpenURIDispatcher extends _QueuingAppEventDispatcher<OpenURIHandler> {
378
void performUsing(final OpenURIHandler handler, final _NativeEvent event) {
379
final String urlString = event.get(0);
380
try {
381
handler.openURI(new OpenURIEvent(new URI(urlString)));
382
} catch (final URISyntaxException e) {
383
throw new RuntimeException(e);
384
}
385
}
386
}
387
388
class _QuitDispatcher extends _AppEventDispatcher<QuitHandler> {
389
void performDefaultAction(final _NativeEvent event) {
390
obtainQuitResponse().performQuit();
391
}
392
393
void performUsing(final QuitHandler handler, final _NativeEvent event) {
394
final QuitResponse response = obtainQuitResponse(); // obtains the "current" quit response
395
handler.handleQuitRequestWith(new QuitEvent(), response);
396
}
397
}
398
399
400
// -- ABSTRACT QUEUE/EVENT/LISTENER HELPERS --
401
402
// generic little "raw event" that's constructed easily from the native callbacks
403
static class _NativeEvent {
404
Object[] args;
405
406
public _NativeEvent(final Object... args) {
407
this.args = args;
408
}
409
410
@SuppressWarnings("unchecked")
411
<T> T get(final int i) {
412
if (args == null) return null;
413
return (T)args[i];
414
}
415
}
416
417
abstract class _AppEventMultiplexor<L> {
418
private final Map<L, AppContext> listenerToAppContext =
419
new IdentityHashMap<L, AppContext>();
420
boolean nativeListenerRegistered;
421
422
// called from AppKit Thread-0
423
void dispatch(final _NativeEvent event, final Object... args) {
424
// grab a local ref to the listeners and its contexts as an array of the map's entries
425
final ArrayList<Map.Entry<L, AppContext>> localEntries;
426
synchronized (this) {
427
if (listenerToAppContext.size() == 0) {
428
return;
429
}
430
localEntries = new ArrayList<Map.Entry<L, AppContext>>(listenerToAppContext.size());
431
localEntries.addAll(listenerToAppContext.entrySet());
432
}
433
434
for (final Map.Entry<L, AppContext> e : localEntries) {
435
final L listener = e.getKey();
436
final AppContext listenerContext = e.getValue();
437
SunToolkit.invokeLaterOnAppContext(listenerContext, new Runnable() {
438
public void run() {
439
performOnListener(listener, event);
440
}
441
});
442
}
443
}
444
445
synchronized void addListener(final L listener) {
446
setListenerContext(listener, AppContext.getAppContext());
447
448
if (!nativeListenerRegistered) {
449
registerNativeListener();
450
nativeListenerRegistered = true;
451
}
452
}
453
454
synchronized void removeListener(final L listener) {
455
listenerToAppContext.remove(listener);
456
}
457
458
abstract void performOnListener(L listener, final _NativeEvent event);
459
void registerNativeListener() { }
460
461
private void setListenerContext(L listener, AppContext listenerContext) {
462
if (listenerContext == null) {
463
throw new RuntimeException(
464
"Attempting to add a listener from a thread group without AppContext");
465
}
466
listenerToAppContext.put(listener, AppContext.getAppContext());
467
}
468
}
469
470
abstract class _BooleanAppEventMultiplexor<L, E> extends _AppEventMultiplexor<L> {
471
@Override
472
void performOnListener(L listener, final _NativeEvent event) {
473
final boolean isTrue = Boolean.TRUE.equals(event.get(0));
474
final E e = createEvent(isTrue);
475
if (isTrue) {
476
performTrueEventOn(listener, e);
477
} else {
478
performFalseEventOn(listener, e);
479
}
480
}
481
482
abstract E createEvent(final boolean isTrue);
483
abstract void performTrueEventOn(final L listener, final E e);
484
abstract void performFalseEventOn(final L listener, final E e);
485
}
486
487
/*
488
* Ensures that setting and obtaining an app event handler is done in
489
* both a thread-safe manner, and that user code is performed on the
490
* AWT EventQueue thread.
491
*
492
* Allows native to blindly lob new events into the dispatcher,
493
* knowing that they will only be dispatched once a handler is set.
494
*
495
* User code is not (and should not be) run under any synchronized lock.
496
*/
497
abstract class _AppEventDispatcher<H> {
498
H _handler;
499
AppContext handlerContext;
500
501
// called from AppKit Thread-0
502
void dispatch(final _NativeEvent event) {
503
// grab a local ref to the handler
504
final H localHandler;
505
final AppContext localHandlerContext;
506
synchronized (_AppEventDispatcher.this) {
507
localHandler = _handler;
508
localHandlerContext = handlerContext;
509
}
510
511
if (localHandler == null) {
512
performDefaultAction(event);
513
} else {
514
SunToolkit.invokeLaterOnAppContext(localHandlerContext, new Runnable() {
515
public void run() {
516
performUsing(localHandler, event);
517
}
518
});
519
}
520
}
521
522
synchronized void setHandler(final H handler) {
523
this._handler = handler;
524
525
setHandlerContext(AppContext.getAppContext());
526
527
// if a new handler is installed, block addition of legacy ApplicationListeners
528
if (handler == legacyHandler) return;
529
legacyHandler.blockLegacyAPI();
530
}
531
532
void performDefaultAction(final _NativeEvent event) { } // by default, do nothing
533
abstract void performUsing(final H handler, final _NativeEvent event);
534
535
protected void setHandlerContext(AppContext ctx) {
536
if (ctx == null) {
537
throw new RuntimeException(
538
"Attempting to set a handler from a thread group without AppContext");
539
}
540
541
handlerContext = ctx;
542
}
543
}
544
545
abstract class _QueuingAppEventDispatcher<H> extends _AppEventDispatcher<H> {
546
List<_NativeEvent> queuedEvents = new LinkedList<_NativeEvent>();
547
548
@Override
549
void dispatch(final _NativeEvent event) {
550
synchronized (this) {
551
// dispatcher hasn't started yet
552
if (queuedEvents != null) {
553
queuedEvents.add(event);
554
return;
555
}
556
}
557
558
super.dispatch(event);
559
}
560
561
synchronized void setHandler(final H handler) {
562
this._handler = handler;
563
564
setHandlerContext(AppContext.getAppContext());
565
566
// dispatch any events in the queue
567
if (queuedEvents != null) {
568
// grab a local ref to the queue, so the real one can be nulled out
569
final java.util.List<_NativeEvent> localQueuedEvents = queuedEvents;
570
queuedEvents = null;
571
if (localQueuedEvents.size() != 0) {
572
for (final _NativeEvent arg : localQueuedEvents) {
573
dispatch(arg);
574
}
575
}
576
}
577
578
// if a new handler is installed, block addition of legacy ApplicationListeners
579
if (handler == legacyHandler) return;
580
legacyHandler.blockLegacyAPI();
581
}
582
}
583
}
584
585