< prev index next >

src/java.desktop/share/classes/java/awt/SequencedEvent.java

Print this page




   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 java.awt;
  27 


  28 import java.util.LinkedList;
  29 import sun.awt.AWTAccessor;
  30 import sun.awt.AppContext;
  31 import sun.awt.SunToolkit;
  32 
  33 /**
  34  * A mechanism for ensuring that a series of AWTEvents are executed in a
  35  * precise order, even across multiple AppContexts. The nested events will be
  36  * dispatched in the order in which their wrapping SequencedEvents were
  37  * constructed. The only exception to this rule is if the peer of the target of
  38  * the nested event was destroyed (with a call to Component.removeNotify)
  39  * before the wrapping SequencedEvent was able to be dispatched. In this case,
  40  * the nested event is never dispatched.
  41  *
  42  * @author David Mendenhall
  43  */
  44 class SequencedEvent extends AWTEvent implements ActiveEvent {
  45     /*
  46      * serialVersionUID
  47      */
  48     private static final long serialVersionUID = 547742659238625067L;
  49 
  50     private static final int ID =
  51         java.awt.event.FocusEvent.FOCUS_LAST + 1;
  52     private static final LinkedList<SequencedEvent> list = new LinkedList<>();
  53 
  54     private final AWTEvent nested;
  55     private AppContext appContext;
  56     private boolean disposed;
  57 


  58     static {
  59         AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
  60             public AWTEvent getNested(AWTEvent sequencedEvent) {
  61                 return ((SequencedEvent)sequencedEvent).nested;
  62             }
  63             public boolean isSequencedEvent(AWTEvent event) {
  64                 return event instanceof SequencedEvent;
  65             }
  66 
  67             public AWTEvent create(AWTEvent event) {
  68                 return new SequencedEvent(event);
  69             }
  70         });







  71     }
  72 
  73     /**
  74      * Constructs a new SequencedEvent which will dispatch the specified
  75      * nested event.
  76      *
  77      * @param nested the AWTEvent which this SequencedEvent's dispatch()
  78      *        method will dispatch
  79      */
  80     public SequencedEvent(AWTEvent nested) {
  81         super(nested.getSource(), ID);
  82         this.nested = nested;
  83         // All AWTEvents that are wrapped in SequencedEvents are (at
  84         // least currently) implicitly generated by the system
  85         SunToolkit.setSystemGenerated(nested);















  86         synchronized (SequencedEvent.class) {
  87             list.add(this);
  88         }
  89     }
  90 
  91     /**
  92      * Dispatches the nested event after all previous nested events have been
  93      * dispatched or disposed. If this method is invoked before all previous nested events
  94      * have been dispatched, then this method blocks until such a point is
  95      * reached.
  96      * While waiting disposes nested events to disposed AppContext
  97      *
  98      * NOTE: Locking protocol.  Since dispose() can get EventQueue lock,
  99      * dispatch() shall never call dispose() while holding the lock on the list,
 100      * as EventQueue lock is held during dispatching.  The locks should be acquired
 101      * in the same order.
 102      */
 103     public final void dispatch() {
 104         try {
 105             appContext = AppContext.getAppContext();
 106 
 107             if (getFirst() != this) {
 108                 if (EventQueue.isDispatchThread()) {

 109                     EventDispatchThread edt = (EventDispatchThread)
 110                         Thread.currentThread();
 111                     edt.pumpEvents(SentEvent.ID, new Conditional() {
 112                         public boolean evaluate() {
 113                             return !SequencedEvent.this.isFirstOrDisposed();
 114                         }
 115                     });















 116                 } else {
 117                     while(!isFirstOrDisposed()) {
 118                         synchronized (SequencedEvent.class) {
 119                             try {
 120                                 SequencedEvent.class.wait(1000);
 121                             } catch (InterruptedException e) {
 122                                 break;
 123                             }
 124                         }
 125                     }
 126                 }
 127             }
 128 
 129             if (!disposed) {
 130                 KeyboardFocusManager.getCurrentKeyboardFocusManager().
 131                     setCurrentSequencedEvent(this);
 132                 Toolkit.getEventQueue().dispatchEvent(nested);
 133             }
 134         } finally {
 135             dispose();




   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 java.awt;
  27 
  28 import java.security.AccessController;
  29 import java.security.PrivilegedAction;
  30 import java.util.LinkedList;
  31 import sun.awt.AWTAccessor;
  32 import sun.awt.AppContext;
  33 import sun.awt.SunToolkit;
  34 
  35 /**
  36  * A mechanism for ensuring that a series of AWTEvents are executed in a
  37  * precise order, even across multiple AppContexts. The nested events will be
  38  * dispatched in the order in which their wrapping SequencedEvents were
  39  * constructed. The only exception to this rule is if the peer of the target of
  40  * the nested event was destroyed (with a call to Component.removeNotify)
  41  * before the wrapping SequencedEvent was able to be dispatched. In this case,
  42  * the nested event is never dispatched.
  43  *
  44  * @author David Mendenhall
  45  */
  46 class SequencedEvent extends AWTEvent implements ActiveEvent {
  47     /*
  48      * serialVersionUID
  49      */
  50     private static final long serialVersionUID = 547742659238625067L;
  51 
  52     private static final int ID =
  53         java.awt.event.FocusEvent.FOCUS_LAST + 1;
  54     private static final LinkedList<SequencedEvent> list = new LinkedList<>();
  55 
  56     private final AWTEvent nested;
  57     private AppContext appContext;
  58     private boolean disposed;
  59 
  60     private static boolean fxAppThreadIsDispatchThread;
  61     private Thread fxCheckSequenceThread;
  62     static {
  63         AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
  64             public AWTEvent getNested(AWTEvent sequencedEvent) {
  65                 return ((SequencedEvent)sequencedEvent).nested;
  66             }
  67             public boolean isSequencedEvent(AWTEvent event) {
  68                 return event instanceof SequencedEvent;
  69             }
  70 
  71             public AWTEvent create(AWTEvent event) {
  72                 return new SequencedEvent(event);
  73             }
  74         });
  75         AccessController.doPrivileged(new PrivilegedAction<Object>() {
  76             public Object run() {
  77                 fxAppThreadIsDispatchThread = 
  78                         "true".equals(System.getProperty("javafx.embed.singleThread"));               
  79                 return null;
  80             }
  81         });                        
  82     }
  83 
  84     /**
  85      * Constructs a new SequencedEvent which will dispatch the specified
  86      * nested event.
  87      *
  88      * @param nested the AWTEvent which this SequencedEvent's dispatch()
  89      *        method will dispatch
  90      */
  91     public SequencedEvent(AWTEvent nested) {
  92         super(nested.getSource(), ID);
  93         this.nested = nested;
  94         // All AWTEvents that are wrapped in SequencedEvents are (at
  95         // least currently) implicitly generated by the system
  96         SunToolkit.setSystemGenerated(nested);
  97         
  98         if (fxAppThreadIsDispatchThread) {
  99             fxCheckSequenceThread = new Thread() {
 100                 @Override
 101                 public void run() {
 102                     while(!isFirstOrDisposed()) {
 103                         try {
 104                             Thread.sleep(100);
 105                         } catch (InterruptedException e) {
 106                             break;
 107                         }
 108                     }
 109                 }
 110             };
 111         }
 112         synchronized (SequencedEvent.class) {
 113             list.add(this);
 114         }
 115     }
 116 
 117     /**
 118      * Dispatches the nested event after all previous nested events have been
 119      * dispatched or disposed. If this method is invoked before all previous nested events
 120      * have been dispatched, then this method blocks until such a point is
 121      * reached.
 122      * While waiting disposes nested events to disposed AppContext
 123      *
 124      * NOTE: Locking protocol.  Since dispose() can get EventQueue lock,
 125      * dispatch() shall never call dispose() while holding the lock on the list,
 126      * as EventQueue lock is held during dispatching.  The locks should be acquired
 127      * in the same order.
 128      */
 129     public final void dispatch() {
 130         try {
 131             appContext = AppContext.getAppContext();
 132 
 133             if (getFirst() != this) {
 134                 if (EventQueue.isDispatchThread()) {
 135                     if (Thread.currentThread() instanceof EventDispatchThread) {
 136                         EventDispatchThread edt = (EventDispatchThread)
 137                                 Thread.currentThread();
 138                         edt.pumpEvents(SentEvent.ID, new Conditional() {
 139                             public boolean evaluate() {
 140                                 return !SequencedEvent.this.isFirstOrDisposed();
 141                             }
 142                         });
 143                     } else {
 144                         if (fxAppThreadIsDispatchThread) {
 145                             fxCheckSequenceThread.start();
 146                             try {
 147                                 // check if event is dispatched or disposed
 148                                 // but since this user app thread is same as
 149                                 // dispatch thread in fx when run with
 150                                 // javafx.embed.singleThread=true
 151                                 // we do not wait infinitely to avoid deadlock
 152                                 // as dispatch will ultimately be done by this thread
 153                                 fxCheckSequenceThread.join(500);
 154                             } catch (InterruptedException e) {
 155                             }
 156                         }
 157                     }                    
 158                 } else {
 159                     while(!isFirstOrDisposed()) {
 160                         synchronized (SequencedEvent.class) {
 161                             try {
 162                                 SequencedEvent.class.wait(1000);
 163                             } catch (InterruptedException e) {
 164                                 break;
 165                             }
 166                         }
 167                     }
 168                 }
 169             }
 170 
 171             if (!disposed) {
 172                 KeyboardFocusManager.getCurrentKeyboardFocusManager().
 173                     setCurrentSequencedEvent(this);
 174                 Toolkit.getEventQueue().dispatchEvent(nested);
 175             }
 176         } finally {
 177             dispose();


< prev index next >