< prev index next >

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

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -25,11 +25,13 @@
 
 package java.awt;
 
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.ArrayList;
 import java.util.LinkedList;
+
 import sun.awt.AWTAccessor;
 import sun.awt.AppContext;
 import sun.awt.SunToolkit;
 
 /**

@@ -51,13 +53,15 @@
 
     private static final int ID =
         java.awt.event.FocusEvent.FOCUS_LAST + 1;
     private static final LinkedList<SequencedEvent> list = new LinkedList<>();
 
+    private static final Object SEQUENCED_EVENT_KEY = new Object();
+
     private final AWTEvent nested;
-    private AppContext appContext;
-    private boolean disposed;
+    private volatile AppContext appContext;
+    private volatile boolean disposed;
 
     private static boolean fxAppThreadIsDispatchThread;
     private Thread fxCheckSequenceThread;
     static {
         AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {

@@ -131,10 +135,12 @@
             appContext = AppContext.getAppContext();
 
             if (getFirst() != this) {
                 if (EventQueue.isDispatchThread()) {
                     if (Thread.currentThread() instanceof EventDispatchThread) {
+                        getWaitingEvents().add(this);
+                        dispatchWaitingEvents();
                         EventDispatchThread edt = (EventDispatchThread)
                                 Thread.currentThread();
                         edt.pumpEvents(ID, () -> !SequencedEvent.this.isFirstOrDisposed());
                     } else {
                         if (fxAppThreadIsDispatchThread) {

@@ -173,10 +179,42 @@
             dispose();
         }
     }
 
     /**
+     * Dispatching waiting events if such event became first or disposed.
+     */
+    private static void dispatchWaitingEvents() {
+        ArrayList<SequencedEvent> waitingEvents = getWaitingEvents();
+        for (int i = 0; i < waitingEvents.size(); i++) {
+            SequencedEvent event = waitingEvents.get(i);
+            if (event.isFirstOrDisposed()) {
+                // found the first event, need to dispatch it/recheck the queue
+                waitingEvents.remove(i);
+                if (!event.disposed) {
+                    event.dispatch();
+                }
+                i = 0; // start from the beginning
+            }
+        }
+    }
+
+    /**
+     * Returns the list of waiting events per-Appcontext.
+     */
+    @SuppressWarnings("unchecked")
+    private static ArrayList<SequencedEvent> getWaitingEvents() {
+        AppContext appContext = AppContext.getAppContext();
+        Object list = appContext.get(SEQUENCED_EVENT_KEY);
+        if (list == null) {
+            list = new ArrayList<>();
+            appContext.put(SEQUENCED_EVENT_KEY, list);
+        }
+        return (ArrayList<SequencedEvent>) list;
+    }
+
+    /**
      * true only if event exists and nested source appContext is disposed.
      */
     private static final boolean isOwnerAppContextDisposed(SequencedEvent se) {
         if (se != null) {
             Object target = se.nested.getSource();

@@ -239,29 +277,52 @@
             }
             disposed = true;
         }
         // Wake myself up
         if (appContext != null) {
-            SunToolkit.postEvent(appContext, new SentEvent());
+            SunToolkit.postEvent(appContext, new Wakeup());
         }
 
         SequencedEvent next = null;
 
         synchronized (SequencedEvent.class) {
           SequencedEvent.class.notifyAll();
 
           if (list.getFirst() == this) {
               list.removeFirst();
-
+          } else {
+              list.remove(this);
+          }
               if (!list.isEmpty()) {
                     next = list.getFirst();
               }
+        }
+        // Wake up waiting threads
+        if (next != null) {
+            if (next.appContext != null) {
+                SunToolkit.postEvent(next.appContext, new Wakeup());
           } else {
-              list.remove(this);
+                // Appcontext of the next event still unknown, try all
+                for (AppContext appContext : AppContext.getAppContexts()) {
+                    SunToolkit.postEvent(appContext, new Wakeup());
           }
       }
-        // Wake up waiting threads
-        if (next != null && next.appContext != null) {
-            SunToolkit.postEvent(next.appContext, new SentEvent());
+        }
+    }
+
+    /**
+     * This event is used to wakeup the EDT if it waiting for a SequencedEvent.
+     */
+    private static final class Wakeup extends AWTEvent implements ActiveEvent {
+
+        private static final long serialVersionUID = -4585374989028949074L;
+
+        Wakeup() {
+            super(new Object(), SequencedEvent.ID);
+        }
+
+        @Override
+        public void dispatch() {
+            dispatchWaitingEvents();
         }
     }
 }
< prev index next >