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