# HG changeset patch # User Jaroslav Tulach # Date 1337766669 -7200 # Node ID 4ed8674de3059c1278ea6fb229acfd17b5803f83 # Parent 78cea258caaba3980ba186c426da82c8fe41bfd7 Allowing JavaFX to dispatchEvent in its own, dedicated FX dispatch thread diff -r 78cea258caab -r 4ed8674de305 src/share/classes/java/awt/Container.java --- a/src/share/classes/java/awt/Container.java Thu Mar 29 13:02:24 2012 -0700 +++ b/src/share/classes/java/awt/Container.java Wed May 23 11:51:09 2012 +0200 @@ -2887,8 +2887,7 @@ Runnable pumpEventsForHierarchy = new Runnable() { public void run() { - EventDispatchThread dispatchThread = - (EventDispatchThread)Thread.currentThread(); + EventDispatchThread dispatchThread = EventDispatchThread.findCurrent(); dispatchThread.pumpEventsForHierarchy( new Conditional() { public boolean evaluate() { diff -r 78cea258caab -r 4ed8674de305 src/share/classes/java/awt/DefaultKeyboardFocusManager.java --- a/src/share/classes/java/awt/DefaultKeyboardFocusManager.java Thu Mar 29 13:02:24 2012 -0700 +++ b/src/share/classes/java/awt/DefaultKeyboardFocusManager.java Wed May 23 11:51:09 2012 +0200 @@ -237,8 +237,7 @@ } SunToolkit.postEvent(targetAppContext, se); if (EventQueue.isDispatchThread()) { - EventDispatchThread edt = (EventDispatchThread) - Thread.currentThread(); + EventDispatchThread edt = EventDispatchThread.findCurrent(); edt.pumpEvents(SentEvent.ID, new Conditional() { public boolean evaluate() { return !se.dispatched && !targetAppContext.isDisposed(); diff -r 78cea258caab -r 4ed8674de305 src/share/classes/java/awt/EventDispatchThread.java --- a/src/share/classes/java/awt/EventDispatchThread.java Thu Mar 29 13:02:24 2012 -0700 +++ b/src/share/classes/java/awt/EventDispatchThread.java Wed May 23 11:51:09 2012 +0200 @@ -25,19 +25,15 @@ package java.awt; -import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.ActionEvent; import java.awt.event.WindowEvent; import java.lang.reflect.Method; -import java.security.AccessController; -import sun.security.action.GetPropertyAction; -import sun.awt.AWTAutoShutdown; -import sun.awt.SunToolkit; -import sun.awt.AppContext; import java.util.ArrayList; -import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; import sun.util.logging.PlatformLogger; import sun.awt.dnd.SunDragSourceContextPeer; @@ -62,7 +58,7 @@ * * @since 1.1 */ -class EventDispatchThread extends Thread { +final class EventDispatchThread { private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread"); @@ -70,14 +66,51 @@ private boolean doDispatch = true; private volatile boolean shutdown = false; - private static final int ANY_EVENT = -1; + static final int ANY_EVENT = -1; + private final Executor executor; private ArrayList eventFilters = new ArrayList(); - EventDispatchThread(ThreadGroup group, String name, EventQueue queue) { - super(group, name); + EventDispatchThread(ThreadGroup group, String name, EventQueue queue, ClassLoader l) { + // right now using simple executor that sort of mimics the old + // behavior of the run() method of EventDispatchThread. But when + // running together with FX, the executor should dispatch the runnable + // using Platform.invokeLater to share the same processing thread + executor = defaultThread(group, name, l); setEventQueue(queue); } + + private static Executor defaultThread(ThreadGroup group, String name, ClassLoader classLoader) { + class ExecRuns implements Executor, Runnable { + final BlockingQueue toRun = new LinkedBlockingQueue<>(); + @Override + public void execute(Runnable command) { + toRun.add(command); + } + + @Override + public void run() { + while (true) { + Runnable r; + try { + r = toRun.take(); + } catch (InterruptedException ex) { + eventLog.severe(ex.getMessage(), ex); + continue; + } + r.run(); + } + } + } + ExecRuns er = new ExecRuns(); + + Thread t = new Thread(group, name); + t.setContextClassLoader(classLoader); + t.setPriority(Thread.NORM_PRIORITY + 1); + t.setDaemon(false); + t.start(); + return er; + } /* * Must be called on EDT only, that's why no synchronization @@ -88,23 +121,29 @@ public void interrupt() { shutdown = true; - super.interrupt(); +//XXX super.interrupt(); } - public void run() { - while (true) { - try { - pumpEvents(new Conditional() { - public boolean evaluate() { - return true; + public void processEvents() { + executor.execute(new Runnable() { + @Override + public void run() { + try { + // XXX: the meaning now should be: the pumpEvents processes + // currently pending events, and then it returns without + // any blocking + pumpEvents(new Conditional() { + public boolean evaluate() { + return true; + } + }); + } finally { + if(getEventQueue().detachDispatchThread(this, shutdown)) { + return; } - }); - } finally { - if(getEventQueue().detachDispatchThread(this, shutdown)) { - break; } } - } + }); } // MacOSX change: @@ -155,6 +194,11 @@ pumpEventsForFilter(ANY_EVENT, cond, filter); } + //XXX + boolean isInterrupted() { + return false; + } + void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) { addEventFilter(filter); doDispatch = true; @@ -195,6 +239,10 @@ eventFilters.remove(filter); } } + + boolean blockWhenNoEvent() { + return true; + } void pumpOneEventForFilters(int id) { AWTEvent event = null; @@ -210,7 +258,10 @@ if (delegate != null && id == ANY_EVENT) { event = delegate.getNextEvent(eq); } else { - event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id); + event = eq.getNextEvent(id, blockWhenNoEvent()); + } + if (event == null) { + return; } eventOK = true; @@ -263,7 +314,12 @@ if (eventLog.isLoggable(PlatformLogger.FINE)) { eventLog.fine("Processing exception: " + e); } - getUncaughtExceptionHandler().uncaughtException(this, e); +//XXX getUncaughtExceptionHandler().uncaughtException(this, e); + } + + public static EventDispatchThread findCurrent() { +//XXX return (EventDispatchThread)Thread.currentThread(); + return null; } public synchronized EventQueue getEventQueue() { diff -r 78cea258caab -r 4ed8674de305 src/share/classes/java/awt/EventQueue.java --- a/src/share/classes/java/awt/EventQueue.java Thu Mar 29 13:02:24 2012 -0700 +++ b/src/share/classes/java/awt/EventQueue.java Wed May 23 11:51:09 2012 +0200 @@ -299,9 +299,9 @@ if (theEvent.getSource() != AWTAutoShutdown.getInstance()) { AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread); } - pushPopCond.signalAll(); + signalAll(); } else if (notifyID) { - pushPopCond.signalAll(); + signalAll(); } } else { // The event was not coalesced or has non-Component source. @@ -309,7 +309,7 @@ queues[priority].tail.next = newItem; queues[priority].tail = newItem; if (notifyID) { - pushPopCond.signalAll(); + signalAll(); } } } @@ -484,6 +484,31 @@ return true; } + + final AWTEvent getNextEvent(int id, boolean block) throws InterruptedException { + if (block) { + return (id == EventDispatchThread.ANY_EVENT) ? getNextEvent() : getNextEvent(id); + } + try { + pushPopLock.lock(); + if (id == EventDispatchThread.ANY_EVENT) { + if (noEvents()) { + return null; + } + // XXX: calls SunToolkit.flushPendingEvents under lock now + return getNextEvent(); + } else { + AWTEvent peek = peekEvent(id); + if (peek == null) { + return null; + } + // XXX: calls SunToolkit.flushPendingEvents under lock now + return getNextEvent(id); + } + } finally { + pushPopLock.unlock(); + } + } /** * Removes an event from the EventQueue and @@ -853,7 +878,7 @@ appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue); } - pushPopCond.signalAll(); + signalAll(); } finally { pushPopLock.unlock(); } @@ -918,7 +943,7 @@ // pick up a new EventQueue topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable)); - pushPopCond.signalAll(); + signalAll(); } finally { pushPopLock.unlock(); } @@ -1010,16 +1035,14 @@ EventDispatchThread t = new EventDispatchThread(threadGroup, name, - EventQueue.this); - t.setContextClassLoader(classLoader); - t.setPriority(Thread.NORM_PRIORITY + 1); - t.setDaemon(false); + EventQueue.this, + classLoader + ); return t; } } ); AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread); - dispatchThread.start(); } } finally { pushPopLock.unlock(); @@ -1252,7 +1275,7 @@ // Forward call to the top of EventQueue stack. nextQueue.wakeup(isShutdown); } else if (dispatchThread != null) { - pushPopCond.signalAll(); + signalAll(); } else if (!isShutdown) { initDispatchThread(); } @@ -1260,8 +1283,15 @@ pushPopLock.unlock(); } } + + private void signalAll() { + pushPopCond.signalAll(); + + // new event delivered - requesting new processing + // of pending events + dispatchThread.processEvents(); + } } - /** * The Queue object holds pointers to the beginning and end of one internal * queue. An EventQueue object is composed of multiple internal Queues, one diff -r 78cea258caab -r 4ed8674de305 src/share/classes/java/awt/SequencedEvent.java --- a/src/share/classes/java/awt/SequencedEvent.java Thu Mar 29 13:02:24 2012 -0700 +++ b/src/share/classes/java/awt/SequencedEvent.java Wed May 23 11:51:09 2012 +0200 @@ -90,8 +90,7 @@ if (getFirst() != this) { if (EventQueue.isDispatchThread()) { - EventDispatchThread edt = (EventDispatchThread) - Thread.currentThread(); + EventDispatchThread edt = EventDispatchThread.findCurrent(); edt.pumpEvents(SentEvent.ID, new Conditional() { public boolean evaluate() { return !SequencedEvent.this.isFirstOrDisposed();