jdk/src/macosx/classes/com/apple/eawt/_AppEventHandler.java
changeset 18760 438afe2fc852
parent 12281 40f247734390
equal deleted inserted replaced
18759:678de8e7eb93 18760:438afe2fc852
     1 /*
     1 /*
     2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    29 import java.awt.event.WindowEvent;
    29 import java.awt.event.WindowEvent;
    30 import java.io.File;
    30 import java.io.File;
    31 import java.net.*;
    31 import java.net.*;
    32 import java.util.*;
    32 import java.util.*;
    33 import java.util.List;
    33 import java.util.List;
       
    34 import sun.awt.AppContext;
       
    35 import sun.awt.SunToolkit;
    34 
    36 
    35 import com.apple.eawt.AppEvent.*;
    37 import com.apple.eawt.AppEvent.*;
    36 
    38 
    37 class _AppEventHandler {
    39 class _AppEventHandler {
    38     private static final int NOTIFY_ABOUT = 1;
    40     private static final int NOTIFY_ABOUT = 1;
   267             handler.handleOpenApp();
   269             handler.handleOpenApp();
   268         }
   270         }
   269     }
   271     }
   270 
   272 
   271     class _AppReOpenedDispatcher extends _AppEventMultiplexor<AppReOpenedListener> {
   273     class _AppReOpenedDispatcher extends _AppEventMultiplexor<AppReOpenedListener> {
   272         void performOnListeners(final List<AppReOpenedListener> listeners, final _NativeEvent event) {
   274         void performOnListener(AppReOpenedListener listener, final _NativeEvent event) {
   273             final AppReOpenedEvent e = new AppReOpenedEvent();
   275             final AppReOpenedEvent e = new AppReOpenedEvent();
   274             for (final AppReOpenedListener listener : listeners) {
   276             listener.appReOpened(e);
   275                 listener.appReOpened(e);
       
   276             }
       
   277         }
   277         }
   278     }
   278     }
   279 
   279 
   280     class _AppForegroundDispatcher extends _BooleanAppEventMultiplexor<AppForegroundListener, AppForegroundEvent> {
   280     class _AppForegroundDispatcher extends _BooleanAppEventMultiplexor<AppForegroundListener, AppForegroundEvent> {
   281         AppForegroundEvent createEvent(final boolean isTrue) { return new AppForegroundEvent(); }
   281         AppForegroundEvent createEvent(final boolean isTrue) { return new AppForegroundEvent(); }
   413             return (T)args[i];
   413             return (T)args[i];
   414         }
   414         }
   415     }
   415     }
   416 
   416 
   417     abstract class _AppEventMultiplexor<L> {
   417     abstract class _AppEventMultiplexor<L> {
   418         final List<L> _listeners = new ArrayList<L>(0);
   418         private final Map<L, AppContext> listenerToAppContext =
       
   419                 new IdentityHashMap<L, AppContext>();
   419         boolean nativeListenerRegistered;
   420         boolean nativeListenerRegistered;
   420 
   421 
   421         // called from AppKit Thread-0
   422         // called from AppKit Thread-0
   422         void dispatch(final _NativeEvent event, final Object... args) {
   423         void dispatch(final _NativeEvent event, final Object... args) {
   423             // grab a local ref to the listeners
   424             // grab a local ref to the listeners and its contexts as an array of the map's entries
   424             final List<L> localListeners;
   425             final ArrayList<Map.Entry<L, AppContext>> localEntries;
   425             synchronized (this) {
   426             synchronized (this) {
   426                 if (_listeners.size() == 0) return;
   427                 if (listenerToAppContext.size() == 0) {
   427                 localListeners = new ArrayList<L>(_listeners);
   428                     return;
   428             }
       
   429 
       
   430             EventQueue.invokeLater(new Runnable() {
       
   431                 public void run() {
       
   432                     performOnListeners(localListeners, event);
       
   433                 }
   429                 }
   434             });
   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             }
   435         }
   443         }
   436 
   444 
   437         synchronized void addListener(final L listener) {
   445         synchronized void addListener(final L listener) {
       
   446             setListenerContext(listener, AppContext.getAppContext());
       
   447 
   438             if (!nativeListenerRegistered) {
   448             if (!nativeListenerRegistered) {
   439                 registerNativeListener();
   449                 registerNativeListener();
   440                 nativeListenerRegistered = true;
   450                 nativeListenerRegistered = true;
   441             }
   451             }
   442             _listeners.add(listener);
       
   443         }
   452         }
   444 
   453 
   445         synchronized void removeListener(final L listener) {
   454         synchronized void removeListener(final L listener) {
   446             _listeners.remove(listener);
   455             listenerToAppContext.remove(listener);
   447         }
   456         }
   448 
   457 
   449         abstract void performOnListeners(final List<L> listeners, final _NativeEvent event);
   458         abstract void performOnListener(L listener, final _NativeEvent event);
   450         void registerNativeListener() { }
   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         }
   451     }
   468     }
   452 
   469 
   453     abstract class _BooleanAppEventMultiplexor<L, E> extends _AppEventMultiplexor<L> {
   470     abstract class _BooleanAppEventMultiplexor<L, E> extends _AppEventMultiplexor<L> {
   454         @Override
   471         @Override
   455         void performOnListeners(final List<L> listeners, final _NativeEvent event) {
   472         void performOnListener(L listener, final _NativeEvent event) {
   456             final boolean isTrue = Boolean.TRUE.equals(event.get(0));
   473             final boolean isTrue = Boolean.TRUE.equals(event.get(0));
   457             final E e = createEvent(isTrue);
   474             final E e = createEvent(isTrue);
   458             if (isTrue) {
   475             if (isTrue) {
   459                 for (final L listener : listeners) performTrueEventOn(listener, e);
   476                 performTrueEventOn(listener, e);
   460             } else {
   477             } else {
   461                 for (final L listener : listeners) performFalseEventOn(listener, e);
   478                 performFalseEventOn(listener, e);
   462             }
   479             }
   463         }
   480         }
   464 
   481 
   465         abstract E createEvent(final boolean isTrue);
   482         abstract E createEvent(final boolean isTrue);
   466         abstract void performTrueEventOn(final L listener, final E e);
   483         abstract void performTrueEventOn(final L listener, final E e);
   477      *
   494      *
   478      * User code is not (and should not be) run under any synchronized lock.
   495      * User code is not (and should not be) run under any synchronized lock.
   479      */
   496      */
   480     abstract class _AppEventDispatcher<H> {
   497     abstract class _AppEventDispatcher<H> {
   481         H _handler;
   498         H _handler;
       
   499         AppContext handlerContext;
   482 
   500 
   483         // called from AppKit Thread-0
   501         // called from AppKit Thread-0
   484         void dispatch(final _NativeEvent event) {
   502         void dispatch(final _NativeEvent event) {
   485             EventQueue.invokeLater(new Runnable() {
   503             // grab a local ref to the handler
   486                 public void run() {
   504             final H localHandler;
   487                     // grab a local ref to the handler
   505             final AppContext localHandlerContext;
   488                     final H localHandler;
   506             synchronized (_AppEventDispatcher.this) {
   489                     synchronized (_AppEventDispatcher.this) {
   507                 localHandler = _handler;
   490                         localHandler = _handler;
   508                 localHandlerContext = handlerContext;
   491                     }
   509             }
   492 
   510 
   493                     // invoke the handler outside of the synchronized block
   511             if (localHandler == null) {
   494                     if (localHandler == null) {
   512                 performDefaultAction(event);
   495                         performDefaultAction(event);
   513             } else {
   496                     } else {
   514                 SunToolkit.invokeLaterOnAppContext(localHandlerContext, new Runnable() {
       
   515                     public void run() {
   497                         performUsing(localHandler, event);
   516                         performUsing(localHandler, event);
   498                     }
   517                     }
   499                 }
   518                 });
   500             });
   519             }
   501         }
   520         }
   502 
   521 
   503         synchronized void setHandler(final H handler) {
   522         synchronized void setHandler(final H handler) {
   504             this._handler = handler;
   523             this._handler = handler;
       
   524 
       
   525             setHandlerContext(AppContext.getAppContext());
   505 
   526 
   506             // if a new handler is installed, block addition of legacy ApplicationListeners
   527             // if a new handler is installed, block addition of legacy ApplicationListeners
   507             if (handler == legacyHandler) return;
   528             if (handler == legacyHandler) return;
   508             legacyHandler.blockLegacyAPI();
   529             legacyHandler.blockLegacyAPI();
   509         }
   530         }
   510 
   531 
   511         void performDefaultAction(final _NativeEvent event) { } // by default, do nothing
   532         void performDefaultAction(final _NativeEvent event) { } // by default, do nothing
   512         abstract void performUsing(final H handler, final _NativeEvent event);
   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         }
   513     }
   543     }
   514 
   544 
   515     abstract class _QueuingAppEventDispatcher<H> extends _AppEventDispatcher<H> {
   545     abstract class _QueuingAppEventDispatcher<H> extends _AppEventDispatcher<H> {
   516         List<_NativeEvent> queuedEvents = new LinkedList<_NativeEvent>();
   546         List<_NativeEvent> queuedEvents = new LinkedList<_NativeEvent>();
   517 
   547 
   528             super.dispatch(event);
   558             super.dispatch(event);
   529         }
   559         }
   530 
   560 
   531         synchronized void setHandler(final H handler) {
   561         synchronized void setHandler(final H handler) {
   532             this._handler = handler;
   562             this._handler = handler;
       
   563 
       
   564             setHandlerContext(AppContext.getAppContext());
   533 
   565 
   534             // dispatch any events in the queue
   566             // dispatch any events in the queue
   535             if (queuedEvents != null) {
   567             if (queuedEvents != null) {
   536                 // grab a local ref to the queue, so the real one can be nulled out
   568                 // grab a local ref to the queue, so the real one can be nulled out
   537                 final java.util.List<_NativeEvent> localQueuedEvents = queuedEvents;
   569                 final java.util.List<_NativeEvent> localQueuedEvents = queuedEvents;