--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CInputMethod.java Thu Oct 10 02:35:27 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CInputMethod.java Thu Oct 10 11:40:06 2013 +0400
@@ -620,8 +620,7 @@
retString[0] = new String(selectedText);
}}
}, fAwtFocussedComponent);
- } catch (InterruptedException ie) { ie.printStackTrace(); }
- catch (InvocationTargetException ite) { ite.printStackTrace(); }
+ } catch (InvocationTargetException ite) { ite.printStackTrace(); }
synchronized(retString) { return retString[0]; }
}
@@ -669,8 +668,7 @@
}}
}, fAwtFocussedComponent);
- } catch (InterruptedException ie) { ie.printStackTrace(); }
- catch (InvocationTargetException ite) { ite.printStackTrace(); }
+ } catch (InvocationTargetException ite) { ite.printStackTrace(); }
synchronized(returnValue) { return returnValue; }
}
@@ -695,8 +693,7 @@
returnValue[0] = fIMContext.getInsertPositionOffset();
}}
}, fAwtFocussedComponent);
- } catch (InterruptedException ie) { ie.printStackTrace(); }
- catch (InvocationTargetException ite) { ite.printStackTrace(); }
+ } catch (InvocationTargetException ite) { ite.printStackTrace(); }
returnValue[1] = fCurrentTextLength;
synchronized(returnValue) { return returnValue; }
@@ -743,8 +740,7 @@
}
}}
}, fAwtFocussedComponent);
- } catch (InterruptedException ie) { ie.printStackTrace(); }
- catch (InvocationTargetException ite) { ite.printStackTrace(); }
+ } catch (InvocationTargetException ite) { ite.printStackTrace(); }
synchronized(rect) { return rect; }
}
@@ -764,8 +760,7 @@
insertPositionOffset[0] = fIMContext.getInsertPositionOffset();
}}
}, fAwtFocussedComponent);
- } catch (InterruptedException ie) { ie.printStackTrace(); }
- catch (InvocationTargetException ite) { ite.printStackTrace(); }
+ } catch (InvocationTargetException ite) { ite.printStackTrace(); }
// This bit of gymnastics ensures that the returned location is within the composed text.
// If it falls outside that region, the input method will commit the text, which is inconsistent with native
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu Oct 10 02:35:27 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu Oct 10 11:40:06 2013 +0400
@@ -884,7 +884,7 @@
//Posting an empty to flush the EventQueue without blocking the main thread
}
}, target);
- } catch (InterruptedException | InvocationTargetException e) {
+ } catch (InvocationTargetException e) {
e.printStackTrace();
}
}
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Thu Oct 10 02:35:27 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Thu Oct 10 11:40:06 2013 +0400
@@ -97,6 +97,6 @@
setVisible(true);
}
}, this);
- } catch (InterruptedException | InvocationTargetException ex) {}
+ } catch (InvocationTargetException ex) {}
}
}
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Oct 10 02:35:27 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Oct 10 11:40:06 2013 +0400
@@ -548,22 +548,18 @@
// Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop
// The InvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop
// Does not dispatch native events while in the loop
- public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException {
+ public static void invokeAndWait(Runnable runnable, Component component) throws InvocationTargetException {
final long mediator = createAWTRunLoopMediator();
InvocationEvent invocationEvent =
- new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event) {
- @Override
- public void dispatch() {
- try {
- super.dispatch();
- } finally {
+ new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(),
+ runnable,
+ () -> {
if (mediator != 0) {
stopAWTRunLoop(mediator);
}
- }
- }
- };
+ },
+ true);
if (component != null) {
AppContext appContext = SunToolkit.targetToAppContext(component);
--- a/jdk/src/share/classes/java/awt/EventQueue.java Thu Oct 10 02:35:27 2013 +0400
+++ b/jdk/src/share/classes/java/awt/EventQueue.java Thu Oct 10 11:40:06 2013 +0400
@@ -1159,6 +1159,10 @@
if (entry.event instanceof SentEvent) {
((SentEvent)entry.event).dispose();
}
+ if (entry.event instanceof InvocationEvent) {
+ AWTAccessor.getInvocationEventAccessor()
+ .dispose((InvocationEvent)entry.event);
+ }
if (prev == null) {
queues[i].head = entry.next;
} else {
--- a/jdk/src/share/classes/java/awt/event/InvocationEvent.java Thu Oct 10 02:35:27 2013 +0400
+++ b/jdk/src/share/classes/java/awt/event/InvocationEvent.java Thu Oct 10 11:40:06 2013 +0400
@@ -25,6 +25,8 @@
package java.awt.event;
+import sun.awt.AWTAccessor;
+
import java.awt.ActiveEvent;
import java.awt.AWTEvent;
@@ -56,6 +58,15 @@
*/
public class InvocationEvent extends AWTEvent implements ActiveEvent {
+ static {
+ AWTAccessor.setInvocationEventAccessor(new AWTAccessor.InvocationEventAccessor() {
+ @Override
+ public void dispose(InvocationEvent invocationEvent) {
+ invocationEvent.finishedDispatching(false);
+ }
+ });
+ }
+
/**
* Marks the first integer id for the range of invocation event ids.
*/
@@ -78,11 +89,21 @@
/**
* The (potentially null) Object whose notifyAll() method will be called
- * immediately after the Runnable.run() method has returned or thrown an exception.
+ * immediately after the Runnable.run() method has returned or thrown an exception
+ * or after the event was disposed.
*
* @see #isDispatched
*/
- protected Object notifier;
+ protected volatile Object notifier;
+
+ /**
+ * The (potentially null) Runnable whose run() method will be called
+ * immediately after the event was dispatched or disposed.
+ *
+ * @see #isDispatched
+ * @since 1.8
+ */
+ private final Runnable listener;
/**
* Indicates whether the <code>run()</code> method of the <code>runnable</code>
@@ -147,7 +168,7 @@
* @see #InvocationEvent(Object, Runnable, Object, boolean)
*/
public InvocationEvent(Object source, Runnable runnable) {
- this(source, runnable, null, false);
+ this(source, INVOCATION_DEFAULT, runnable, null, null, false);
}
/**
@@ -171,7 +192,8 @@
* @param notifier The {@code Object} whose <code>notifyAll</code>
* method will be called after
* <code>Runnable.run</code> has returned or
- * thrown an exception
+ * thrown an exception or after the event was
+ * disposed
* @param catchThrowables Specifies whether <code>dispatch</code>
* should catch Throwable when executing
* the <code>Runnable</code>'s <code>run</code>
@@ -185,7 +207,39 @@
*/
public InvocationEvent(Object source, Runnable runnable, Object notifier,
boolean catchThrowables) {
- this(source, INVOCATION_DEFAULT, runnable, notifier, catchThrowables);
+ this(source, INVOCATION_DEFAULT, runnable, notifier, null, catchThrowables);
+ }
+
+ /**
+ * Constructs an <code>InvocationEvent</code> with the specified
+ * source which will execute the runnable's <code>run</code>
+ * method when dispatched. If listener is non-<code>null</code>,
+ * <code>listener.run()</code> will be called immediately after
+ * <code>run</code> has returned, thrown an exception or the event
+ * was disposed.
+ * <p>This method throws an <code>IllegalArgumentException</code>
+ * if <code>source</code> is <code>null</code>.
+ *
+ * @param source The <code>Object</code> that originated
+ * the event
+ * @param runnable The <code>Runnable</code> whose
+ * <code>run</code> method will be
+ * executed
+ * @param listener The <code>Runnable</code>Runnable whose
+ * <code>run()</code> method will be called
+ * after the {@code InvocationEvent}
+ * was dispatched or disposed
+ * @param catchThrowables Specifies whether <code>dispatch</code>
+ * should catch Throwable when executing
+ * the <code>Runnable</code>'s <code>run</code>
+ * method, or should instead propagate those
+ * Throwables to the EventDispatchThread's
+ * dispatch loop
+ * @throws IllegalArgumentException if <code>source</code> is null
+ */
+ public InvocationEvent(Object source, Runnable runnable, Runnable listener,
+ boolean catchThrowables) {
+ this(source, INVOCATION_DEFAULT, runnable, null, listener, catchThrowables);
}
/**
@@ -208,7 +262,8 @@
* @param notifier The <code>Object</code> whose <code>notifyAll</code>
* method will be called after
* <code>Runnable.run</code> has returned or
- * thrown an exception
+ * thrown an exception or after the event was
+ * disposed
* @param catchThrowables Specifies whether <code>dispatch</code>
* should catch Throwable when executing the
* <code>Runnable</code>'s <code>run</code>
@@ -221,13 +276,18 @@
*/
protected InvocationEvent(Object source, int id, Runnable runnable,
Object notifier, boolean catchThrowables) {
+ this(source, id, runnable, notifier, null, catchThrowables);
+ }
+
+ private InvocationEvent(Object source, int id, Runnable runnable,
+ Object notifier, Runnable listener, boolean catchThrowables) {
super(source, id);
this.runnable = runnable;
this.notifier = notifier;
+ this.listener = listener;
this.catchExceptions = catchThrowables;
this.when = System.currentTimeMillis();
}
-
/**
* Executes the Runnable's <code>run()</code> method and notifies the
* notifier (if any) when <code>run()</code> has returned or thrown an exception.
@@ -251,13 +311,7 @@
runnable.run();
}
} finally {
- dispatched = true;
-
- if (notifier != null) {
- synchronized (notifier) {
- notifier.notifyAll();
- }
- }
+ finishedDispatching(true);
}
}
@@ -331,6 +385,25 @@
}
/**
+ * Called when the event was dispatched or disposed
+ * @param dispatched true if the event was dispatched
+ * false if the event was disposed
+ */
+ private void finishedDispatching(boolean dispatched) {
+ this.dispatched = dispatched;
+
+ if (notifier != null) {
+ synchronized (notifier) {
+ notifier.notifyAll();
+ }
+ }
+
+ if (listener != null) {
+ listener.run();
+ }
+ }
+
+ /**
* Returns a parameter string identifying this event.
* This method is useful for event-logging and for debugging.
*
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java Thu Oct 10 02:35:27 2013 +0400
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java Thu Oct 10 11:40:06 2013 +0400
@@ -31,6 +31,7 @@
import java.awt.KeyboardFocusManager;
import java.awt.DefaultKeyboardFocusManager;
import java.awt.event.InputEvent;
+import java.awt.event.InvocationEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Point2D;
import java.awt.peer.ComponentPeer;
@@ -721,6 +722,13 @@
}
/*
+ * An accessor object for the InvocationEvent class
+ */
+ public interface InvocationEventAccessor {
+ void dispose(InvocationEvent event);
+ }
+
+ /*
* Accessor instances are initialized in the static initializers of
* corresponding AWT classes by using setters defined below.
*/
@@ -748,6 +756,7 @@
private static DefaultKeyboardFocusManagerAccessor defaultKeyboardFocusManagerAccessor;
private static SequencedEventAccessor sequencedEventAccessor;
private static ToolkitAccessor toolkitAccessor;
+ private static InvocationEventAccessor invocationEventAccessor;
/*
* Set an accessor object for the java.awt.Component class.
@@ -1159,4 +1168,18 @@
return toolkitAccessor;
}
+
+ /*
+ * Get the accessor object for the java.awt.event.InvocationEvent class.
+ */
+ public static void setInvocationEventAccessor(InvocationEventAccessor invocationEventAccessor) {
+ AWTAccessor.invocationEventAccessor = invocationEventAccessor;
+ }
+
+ /*
+ * Set the accessor object for the java.awt.event.InvocationEvent class.
+ */
+ public static InvocationEventAccessor getInvocationEventAccessor() {
+ return invocationEventAccessor;
+ }
}