src/java.desktop/share/classes/java/awt/SequencedEvent.java
changeset 52558 08a0bf1592bd
parent 49299 719064f540f3
child 58309 c6f8b2c3dc66
equal deleted inserted replaced
52557:2f6f97629aa7 52558:08a0bf1592bd
    25 
    25 
    26 package java.awt;
    26 package java.awt;
    27 
    27 
    28 import java.security.AccessController;
    28 import java.security.AccessController;
    29 import java.security.PrivilegedAction;
    29 import java.security.PrivilegedAction;
       
    30 import java.util.Iterator;
    30 import java.util.LinkedList;
    31 import java.util.LinkedList;
    31 import sun.awt.AWTAccessor;
    32 import sun.awt.AWTAccessor;
    32 import sun.awt.AppContext;
    33 import sun.awt.AppContext;
    33 import sun.awt.SunToolkit;
    34 import sun.awt.SunToolkit;
    34 
    35 
    54     private static final LinkedList<SequencedEvent> list = new LinkedList<>();
    55     private static final LinkedList<SequencedEvent> list = new LinkedList<>();
    55 
    56 
    56     private final AWTEvent nested;
    57     private final AWTEvent nested;
    57     private AppContext appContext;
    58     private AppContext appContext;
    58     private boolean disposed;
    59     private boolean disposed;
       
    60     private final LinkedList<AWTEvent> pendingEvents = new LinkedList<>();
    59 
    61 
    60     private static boolean fxAppThreadIsDispatchThread;
    62     private static boolean fxAppThreadIsDispatchThread;
    61     private Thread fxCheckSequenceThread;
    63     private Thread fxCheckSequenceThread;
    62     static {
    64     static {
    63         AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
    65         AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
    77                 fxAppThreadIsDispatchThread =
    79                 fxAppThreadIsDispatchThread =
    78                         "true".equals(System.getProperty("javafx.embed.singleThread"));
    80                         "true".equals(System.getProperty("javafx.embed.singleThread"));
    79                 return null;
    81                 return null;
    80             }
    82             }
    81         });
    83         });
       
    84     }
       
    85 
       
    86     private static final class SequencedEventsFilter implements EventFilter {
       
    87         private final SequencedEvent currentSequencedEvent;
       
    88         private SequencedEventsFilter(SequencedEvent currentSequencedEvent) {
       
    89             this.currentSequencedEvent = currentSequencedEvent;
       
    90         }
       
    91         @Override
       
    92         public FilterAction acceptEvent(AWTEvent ev) {
       
    93             if (ev.getID() == ID) {
       
    94                 // Move forward dispatching only if the event is previous
       
    95                 // in SequencedEvent.list. Otherwise, hold it for reposting later.
       
    96                 synchronized (SequencedEvent.class) {
       
    97                     Iterator<SequencedEvent> it = list.iterator();
       
    98                     while (it.hasNext()) {
       
    99                         SequencedEvent iev = it.next();
       
   100                         if (iev.equals(currentSequencedEvent)) {
       
   101                             break;
       
   102                         } else if (iev.equals(ev)) {
       
   103                             return FilterAction.ACCEPT;
       
   104                         }
       
   105                     }
       
   106                 }
       
   107             } else if (ev.getID() == SentEvent.ID) {
       
   108                 return FilterAction.ACCEPT;
       
   109             }
       
   110             currentSequencedEvent.pendingEvents.add(ev);
       
   111             return FilterAction.REJECT;
       
   112         }
    82     }
   113     }
    83 
   114 
    84     /**
   115     /**
    85      * Constructs a new SequencedEvent which will dispatch the specified
   116      * Constructs a new SequencedEvent which will dispatch the specified
    86      * nested event.
   117      * nested event.
   133             if (getFirst() != this) {
   164             if (getFirst() != this) {
   134                 if (EventQueue.isDispatchThread()) {
   165                 if (EventQueue.isDispatchThread()) {
   135                     if (Thread.currentThread() instanceof EventDispatchThread) {
   166                     if (Thread.currentThread() instanceof EventDispatchThread) {
   136                         EventDispatchThread edt = (EventDispatchThread)
   167                         EventDispatchThread edt = (EventDispatchThread)
   137                                 Thread.currentThread();
   168                                 Thread.currentThread();
   138                         edt.pumpEvents(ID, () -> !SequencedEvent.this.isFirstOrDisposed());
   169                         edt.pumpEventsForFilter(() -> !SequencedEvent.this.isFirstOrDisposed(),
       
   170                                 new SequencedEventsFilter(this));
   139                     } else {
   171                     } else {
   140                         if (fxAppThreadIsDispatchThread) {
   172                         if (fxAppThreadIsDispatchThread) {
   141                             fxCheckSequenceThread.start();
   173                             fxCheckSequenceThread.start();
   142                             try {
   174                             try {
   143                                 // check if event is dispatched or disposed
   175                                 // check if event is dispatched or disposed
   237                 KeyboardFocusManager.getCurrentKeyboardFocusManager().
   269                 KeyboardFocusManager.getCurrentKeyboardFocusManager().
   238                     setCurrentSequencedEvent(null);
   270                     setCurrentSequencedEvent(null);
   239             }
   271             }
   240             disposed = true;
   272             disposed = true;
   241         }
   273         }
   242         // Wake myself up
       
   243         if (appContext != null) {
       
   244             SunToolkit.postEvent(appContext, new SentEvent());
       
   245         }
       
   246 
   274 
   247         SequencedEvent next = null;
   275         SequencedEvent next = null;
   248 
   276 
   249         synchronized (SequencedEvent.class) {
   277         synchronized (SequencedEvent.class) {
   250           SequencedEvent.class.notifyAll();
   278           SequencedEvent.class.notifyAll();
   261       }
   289       }
   262         // Wake up waiting threads
   290         // Wake up waiting threads
   263         if (next != null && next.appContext != null) {
   291         if (next != null && next.appContext != null) {
   264             SunToolkit.postEvent(next.appContext, new SentEvent());
   292             SunToolkit.postEvent(next.appContext, new SentEvent());
   265         }
   293         }
       
   294 
       
   295         for(AWTEvent e : pendingEvents) {
       
   296             SunToolkit.postEvent(appContext, e);
       
   297         }
   266     }
   298     }
   267 }
   299 }