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 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
35 import com.apple.eawt.AppEvent.*;
36
37 class _AppEventHandler {
38 private static final int NOTIFY_ABOUT = 1;
39 private static final int NOTIFY_PREFS = 2;
40 private static final int NOTIFY_OPEN_APP = 3;
41 private static final int NOTIFY_REOPEN_APP = 4;
42 private static final int NOTIFY_QUIT = 5;
43 private static final int NOTIFY_SHUTDOWN = 6;
44 private static final int NOTIFY_ACTIVE_APP_GAINED = 7;
45 private static final int NOTIFY_ACTIVE_APP_LOST = 8;
46 private static final int NOTIFY_APP_HIDDEN = 9;
47 private static final int NOTIFY_APP_SHOWN = 10;
48 private static final int NOTIFY_USER_SESSION_ACTIVE = 11;
49 private static final int NOTIFY_USER_SESSION_INACTIVE = 12;
50 private static final int NOTIFY_SCREEN_SLEEP = 13;
51 private static final int NOTIFY_SCREEN_WAKE = 14;
52 private static final int NOTIFY_SYSTEM_SLEEP = 15;
53 private static final int NOTIFY_SYSTEM_WAKE = 16;
252 class _PreferencesDispatcher extends _AppEventDispatcher<PreferencesHandler> {
253 synchronized void setHandler(final PreferencesHandler handler) {
254 super.setHandler(handler);
255
256 _AppMenuBarHandler.getInstance().setPreferencesMenuItemVisible(handler != null);
257 _AppMenuBarHandler.getInstance().setPreferencesMenuItemEnabled(handler != null);
258 }
259
260 void performUsing(final PreferencesHandler handler, final _NativeEvent event) {
261 handler.handlePreferences(new PreferencesEvent());
262 }
263 }
264
265 class _OpenAppDispatcher extends _QueuingAppEventDispatcher<com.apple.eawt._OpenAppHandler> {
266 void performUsing(com.apple.eawt._OpenAppHandler handler, _NativeEvent event) {
267 handler.handleOpenApp();
268 }
269 }
270
271 class _AppReOpenedDispatcher extends _AppEventMultiplexor<AppReOpenedListener> {
272 void performOnListeners(final List<AppReOpenedListener> listeners, final _NativeEvent event) {
273 final AppReOpenedEvent e = new AppReOpenedEvent();
274 for (final AppReOpenedListener listener : listeners) {
275 listener.appReOpened(e);
276 }
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
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 final List<L> _listeners = new ArrayList<L>(0);
419 boolean nativeListenerRegistered;
420
421 // called from AppKit Thread-0
422 void dispatch(final _NativeEvent event, final Object... args) {
423 // grab a local ref to the listeners
424 final List<L> localListeners;
425 synchronized (this) {
426 if (_listeners.size() == 0) return;
427 localListeners = new ArrayList<L>(_listeners);
428 }
429
430 EventQueue.invokeLater(new Runnable() {
431 public void run() {
432 performOnListeners(localListeners, event);
433 }
434 });
435 }
436
437 synchronized void addListener(final L listener) {
438 if (!nativeListenerRegistered) {
439 registerNativeListener();
440 nativeListenerRegistered = true;
441 }
442 _listeners.add(listener);
443 }
444
445 synchronized void removeListener(final L listener) {
446 _listeners.remove(listener);
447 }
448
449 abstract void performOnListeners(final List<L> listeners, final _NativeEvent event);
450 void registerNativeListener() { }
451 }
452
453 abstract class _BooleanAppEventMultiplexor<L, E> extends _AppEventMultiplexor<L> {
454 @Override
455 void performOnListeners(final List<L> listeners, final _NativeEvent event) {
456 final boolean isTrue = Boolean.TRUE.equals(event.get(0));
457 final E e = createEvent(isTrue);
458 if (isTrue) {
459 for (final L listener : listeners) performTrueEventOn(listener, e);
460 } else {
461 for (final L listener : listeners) performFalseEventOn(listener, e);
462 }
463 }
464
465 abstract E createEvent(final boolean isTrue);
466 abstract void performTrueEventOn(final L listener, final E e);
467 abstract void performFalseEventOn(final L listener, final E e);
468 }
469
470 /*
471 * Ensures that setting and obtaining an app event handler is done in
472 * both a thread-safe manner, and that user code is performed on the
473 * AWT EventQueue thread.
474 *
475 * Allows native to blindly lob new events into the dispatcher,
476 * knowing that they will only be dispatched once a handler is set.
477 *
478 * User code is not (and should not be) run under any synchronized lock.
479 */
480 abstract class _AppEventDispatcher<H> {
481 H _handler;
482
483 // called from AppKit Thread-0
484 void dispatch(final _NativeEvent event) {
485 EventQueue.invokeLater(new Runnable() {
486 public void run() {
487 // grab a local ref to the handler
488 final H localHandler;
489 synchronized (_AppEventDispatcher.this) {
490 localHandler = _handler;
491 }
492
493 // invoke the handler outside of the synchronized block
494 if (localHandler == null) {
495 performDefaultAction(event);
496 } else {
497 performUsing(localHandler, event);
498 }
499 }
500 });
501 }
502
503 synchronized void setHandler(final H handler) {
504 this._handler = handler;
505
506 // if a new handler is installed, block addition of legacy ApplicationListeners
507 if (handler == legacyHandler) return;
508 legacyHandler.blockLegacyAPI();
509 }
510
511 void performDefaultAction(final _NativeEvent event) { } // by default, do nothing
512 abstract void performUsing(final H handler, final _NativeEvent event);
513 }
514
515 abstract class _QueuingAppEventDispatcher<H> extends _AppEventDispatcher<H> {
516 List<_NativeEvent> queuedEvents = new LinkedList<_NativeEvent>();
517
518 @Override
519 void dispatch(final _NativeEvent event) {
520 synchronized (this) {
521 // dispatcher hasn't started yet
522 if (queuedEvents != null) {
523 queuedEvents.add(event);
524 return;
525 }
526 }
527
528 super.dispatch(event);
529 }
530
531 synchronized void setHandler(final H handler) {
532 this._handler = handler;
533
534 // dispatch any events in the queue
535 if (queuedEvents != null) {
536 // grab a local ref to the queue, so the real one can be nulled out
537 final java.util.List<_NativeEvent> localQueuedEvents = queuedEvents;
538 queuedEvents = null;
539 if (localQueuedEvents.size() != 0) {
540 for (final _NativeEvent arg : localQueuedEvents) {
541 dispatch(arg);
542 }
543 }
544 }
545
546 // if a new handler is installed, block addition of legacy ApplicationListeners
547 if (handler == legacyHandler) return;
548 legacyHandler.blockLegacyAPI();
549 }
550 }
551 }
|
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;
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
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 }
|