Merge
This commit is contained in:
commit
8baf254d15
@ -61,77 +61,31 @@ import sun.awt.EventQueueDelegate;
|
|||||||
* @since 1.1
|
* @since 1.1
|
||||||
*/
|
*/
|
||||||
class EventDispatchThread extends Thread {
|
class EventDispatchThread extends Thread {
|
||||||
|
|
||||||
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
|
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
|
||||||
|
|
||||||
private EventQueue theQueue;
|
private EventQueue theQueue;
|
||||||
private boolean doDispatch = true;
|
private boolean doDispatch = true;
|
||||||
|
private boolean threadDeathCaught = false;
|
||||||
|
|
||||||
private static final int ANY_EVENT = -1;
|
private static final int ANY_EVENT = -1;
|
||||||
|
|
||||||
private Vector<EventFilter> eventFilters = new Vector<EventFilter>();
|
private Vector<EventFilter> eventFilters = new Vector<EventFilter>();
|
||||||
// used in handleException
|
|
||||||
private int modalFiltersCount = 0;
|
|
||||||
|
|
||||||
EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
|
EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
|
||||||
super(group, name);
|
super(group, name);
|
||||||
theQueue = queue;
|
setEventQueue(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopDispatchingImpl(boolean wait) {
|
|
||||||
// Note: We stop dispatching via a flag rather than using
|
|
||||||
// Thread.interrupt() because we can't guarantee that the wait()
|
|
||||||
// we interrupt will be EventQueue.getNextEvent()'s. -fredx 8-11-98
|
|
||||||
|
|
||||||
StopDispatchEvent stopEvent = new StopDispatchEvent();
|
|
||||||
|
|
||||||
// wait for the dispatcher to complete
|
|
||||||
if (Thread.currentThread() != this) {
|
|
||||||
|
|
||||||
// fix 4122683, 4128923
|
|
||||||
// Post an empty event to ensure getNextEvent is unblocked
|
|
||||||
//
|
|
||||||
// We have to use postEventPrivate instead of postEvent because
|
|
||||||
// EventQueue.pop calls EventDispatchThread.stopDispatching.
|
|
||||||
// Calling SunToolkit.flushPendingEvents in this case could
|
|
||||||
// lead to deadlock.
|
|
||||||
theQueue.postEventPrivate(stopEvent);
|
|
||||||
|
|
||||||
if (wait) {
|
|
||||||
try {
|
|
||||||
join();
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stopEvent.dispatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
theQueue.detachDispatchThread(this, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopDispatching() {
|
|
||||||
stopDispatchingImpl(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopDispatchingLater() {
|
|
||||||
stopDispatchingImpl(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
class StopDispatchEvent extends AWTEvent implements ActiveEvent {
|
|
||||||
/*
|
/*
|
||||||
* serialVersionUID
|
* Must be called on EDT only, that's why no synchronization
|
||||||
*/
|
*/
|
||||||
static final long serialVersionUID = -3692158172100730735L;
|
public void stopDispatching() {
|
||||||
|
|
||||||
public StopDispatchEvent() {
|
|
||||||
super(EventDispatchThread.this,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dispatch() {
|
|
||||||
doDispatch = false;
|
doDispatch = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
|
while (true) {
|
||||||
try {
|
try {
|
||||||
pumpEvents(new Conditional() {
|
pumpEvents(new Conditional() {
|
||||||
public boolean evaluate() {
|
public boolean evaluate() {
|
||||||
@ -139,7 +93,11 @@ class EventDispatchThread extends Thread {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
theQueue.detachDispatchThread(this, true);
|
EventQueue eq = getEventQueue();
|
||||||
|
if (eq.detachDispatchThread(this) || threadDeathCaught) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +148,6 @@ class EventDispatchThread extends Thread {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
eventFilters.add(k, filter);
|
eventFilters.add(k, filter);
|
||||||
modalFiltersCount++;
|
|
||||||
} else {
|
} else {
|
||||||
eventFilters.add(filter);
|
eventFilters.add(filter);
|
||||||
}
|
}
|
||||||
@ -200,28 +157,25 @@ class EventDispatchThread extends Thread {
|
|||||||
|
|
||||||
void removeEventFilter(EventFilter filter) {
|
void removeEventFilter(EventFilter filter) {
|
||||||
synchronized (eventFilters) {
|
synchronized (eventFilters) {
|
||||||
if (eventFilters.contains(filter)) {
|
|
||||||
if (filter instanceof ModalEventFilter) {
|
|
||||||
modalFiltersCount--;
|
|
||||||
}
|
|
||||||
eventFilters.remove(filter);
|
eventFilters.remove(filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
boolean pumpOneEventForFilters(int id) {
|
boolean pumpOneEventForFilters(int id) {
|
||||||
|
AWTEvent event = null;
|
||||||
|
boolean eventOK = false;
|
||||||
try {
|
try {
|
||||||
AWTEvent event;
|
EventQueue eq = null;
|
||||||
boolean eventOK;
|
EventQueueDelegate.Delegate delegate = null;
|
||||||
EventQueueDelegate.Delegate delegate =
|
|
||||||
EventQueueDelegate.getDelegate();
|
|
||||||
do {
|
do {
|
||||||
|
// EventQueue may change during the dispatching
|
||||||
|
eq = getEventQueue();
|
||||||
|
delegate = EventQueueDelegate.getDelegate();
|
||||||
|
|
||||||
if (delegate != null && id == ANY_EVENT) {
|
if (delegate != null && id == ANY_EVENT) {
|
||||||
event = delegate.getNextEvent(theQueue);
|
event = delegate.getNextEvent(eq);
|
||||||
} else {
|
} else {
|
||||||
event = (id == ANY_EVENT)
|
event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id);
|
||||||
? theQueue.getNextEvent()
|
|
||||||
: theQueue.getNextEvent(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
eventOK = true;
|
eventOK = true;
|
||||||
@ -252,13 +206,15 @@ class EventDispatchThread extends Thread {
|
|||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
handle = delegate.beforeDispatch(event);
|
handle = delegate.beforeDispatch(event);
|
||||||
}
|
}
|
||||||
theQueue.dispatchEvent(event);
|
eq.dispatchEvent(event);
|
||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
delegate.afterDispatch(event, handle);
|
delegate.afterDispatch(event, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (ThreadDeath death) {
|
catch (ThreadDeath death) {
|
||||||
|
threadDeathCaught = true;
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -267,12 +223,10 @@ class EventDispatchThread extends Thread {
|
|||||||
// Threads in the AppContext
|
// Threads in the AppContext
|
||||||
|
|
||||||
}
|
}
|
||||||
// Can get and throw only unchecked exceptions
|
catch (Throwable e) {
|
||||||
catch (RuntimeException e) {
|
|
||||||
processException(e);
|
|
||||||
} catch (Error e) {
|
|
||||||
processException(e);
|
processException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,14 +235,14 @@ class EventDispatchThread extends Thread {
|
|||||||
eventLog.fine("Processing exception: " + e);
|
eventLog.fine("Processing exception: " + e);
|
||||||
}
|
}
|
||||||
getUncaughtExceptionHandler().uncaughtException(this, e);
|
getUncaughtExceptionHandler().uncaughtException(this, e);
|
||||||
// don't rethrow the exception to avoid EDT recreation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isDispatching(EventQueue eq) {
|
public synchronized EventQueue getEventQueue() {
|
||||||
return theQueue.equals(eq);
|
return theQueue;
|
||||||
|
}
|
||||||
|
public synchronized void setEventQueue(EventQueue eq) {
|
||||||
|
theQueue = eq;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventQueue getEventQueue() { return theQueue; }
|
|
||||||
|
|
||||||
private static class HierarchyEventFilter implements EventFilter {
|
private static class HierarchyEventFilter implements EventFilter {
|
||||||
private Component modalComponent;
|
private Component modalComponent;
|
||||||
|
@ -138,6 +138,15 @@ public class EventQueue {
|
|||||||
private final Lock pushPopLock;
|
private final Lock pushPopLock;
|
||||||
private final Condition pushPopCond;
|
private final Condition pushPopCond;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dummy runnable to wake up EDT from getNextEvent() after
|
||||||
|
push/pop is performed
|
||||||
|
*/
|
||||||
|
private final static Runnable dummyRunnable = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private EventDispatchThread dispatchThread;
|
private EventDispatchThread dispatchThread;
|
||||||
|
|
||||||
private final ThreadGroup threadGroup =
|
private final ThreadGroup threadGroup =
|
||||||
@ -219,22 +228,22 @@ public class EventQueue {
|
|||||||
* @param theEvent an instance of <code>java.awt.AWTEvent</code>,
|
* @param theEvent an instance of <code>java.awt.AWTEvent</code>,
|
||||||
* or a subclass of it
|
* or a subclass of it
|
||||||
*/
|
*/
|
||||||
final void postEventPrivate(AWTEvent theEvent) {
|
private final void postEventPrivate(AWTEvent theEvent) {
|
||||||
theEvent.isPosted = true;
|
theEvent.isPosted = true;
|
||||||
pushPopLock.lock();
|
pushPopLock.lock();
|
||||||
try {
|
try {
|
||||||
if (dispatchThread == null && nextQueue == null) {
|
if (nextQueue != null) {
|
||||||
|
// Forward the event to the top of EventQueue stack
|
||||||
|
nextQueue.postEventPrivate(theEvent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dispatchThread == null) {
|
||||||
if (theEvent.getSource() == AWTAutoShutdown.getInstance()) {
|
if (theEvent.getSource() == AWTAutoShutdown.getInstance()) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
initDispatchThread();
|
initDispatchThread();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nextQueue != null) {
|
|
||||||
// Forward event to top of EventQueue stack.
|
|
||||||
nextQueue.postEventPrivate(theEvent);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
postEvent(theEvent, getPriority(theEvent));
|
postEvent(theEvent, getPriority(theEvent));
|
||||||
} finally {
|
} finally {
|
||||||
pushPopLock.unlock();
|
pushPopLock.unlock();
|
||||||
@ -242,29 +251,20 @@ public class EventQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int getPriority(AWTEvent theEvent) {
|
private static int getPriority(AWTEvent theEvent) {
|
||||||
if (theEvent instanceof PeerEvent &&
|
if (theEvent instanceof PeerEvent) {
|
||||||
(((PeerEvent)theEvent).getFlags() &
|
PeerEvent peerEvent = (PeerEvent)theEvent;
|
||||||
PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0)
|
if ((peerEvent.getFlags() & PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0) {
|
||||||
{
|
|
||||||
return ULTIMATE_PRIORITY;
|
return ULTIMATE_PRIORITY;
|
||||||
}
|
}
|
||||||
|
if ((peerEvent.getFlags() & PeerEvent.PRIORITY_EVENT) != 0) {
|
||||||
if (theEvent instanceof PeerEvent &&
|
|
||||||
(((PeerEvent)theEvent).getFlags() &
|
|
||||||
PeerEvent.PRIORITY_EVENT) != 0)
|
|
||||||
{
|
|
||||||
return HIGH_PRIORITY;
|
return HIGH_PRIORITY;
|
||||||
}
|
}
|
||||||
|
if ((peerEvent.getFlags() & PeerEvent.LOW_PRIORITY_EVENT) != 0) {
|
||||||
if (theEvent instanceof PeerEvent &&
|
|
||||||
(((PeerEvent)theEvent).getFlags() &
|
|
||||||
PeerEvent.LOW_PRIORITY_EVENT) != 0)
|
|
||||||
{
|
|
||||||
return LOW_PRIORITY;
|
return LOW_PRIORITY;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
int id = theEvent.getID();
|
int id = theEvent.getID();
|
||||||
if (id == PaintEvent.PAINT || id == PaintEvent.UPDATE) {
|
if ((id >= PaintEvent.PAINT_FIRST) && (id <= PaintEvent.PAINT_LAST)) {
|
||||||
return LOW_PRIORITY;
|
return LOW_PRIORITY;
|
||||||
}
|
}
|
||||||
return NORM_PRIORITY;
|
return NORM_PRIORITY;
|
||||||
@ -501,6 +501,22 @@ public class EventQueue {
|
|||||||
SunToolkit.flushPendingEvents();
|
SunToolkit.flushPendingEvents();
|
||||||
pushPopLock.lock();
|
pushPopLock.lock();
|
||||||
try {
|
try {
|
||||||
|
AWTEvent event = getNextEventPrivate();
|
||||||
|
if (event != null) {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
|
||||||
|
pushPopCond.await();
|
||||||
|
} finally {
|
||||||
|
pushPopLock.unlock();
|
||||||
|
}
|
||||||
|
} while(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must be called under the lock. Doesn't call flushPendingEvents()
|
||||||
|
*/
|
||||||
|
AWTEvent getNextEventPrivate() throws InterruptedException {
|
||||||
for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
|
for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
|
||||||
if (queues[i].head != null) {
|
if (queues[i].head != null) {
|
||||||
EventQueueItem entry = queues[i].head;
|
EventQueueItem entry = queues[i].head;
|
||||||
@ -512,12 +528,7 @@ public class EventQueue {
|
|||||||
return entry.event;
|
return entry.event;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
|
return null;
|
||||||
pushPopCond.await();
|
|
||||||
} finally {
|
|
||||||
pushPopLock.unlock();
|
|
||||||
}
|
|
||||||
} while(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AWTEvent getNextEvent(int id) throws InterruptedException {
|
AWTEvent getNextEvent(int id) throws InterruptedException {
|
||||||
@ -659,7 +670,9 @@ public class EventQueue {
|
|||||||
dispatchThread.stopDispatching();
|
dispatchThread.stopDispatching();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
System.err.println("unable to dispatch event: " + event);
|
if (eventLog.isLoggable(PlatformLogger.FINE)) {
|
||||||
|
eventLog.fine("Unable to dispatch event: " + event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -761,15 +774,23 @@ public class EventQueue {
|
|||||||
|
|
||||||
pushPopLock.lock();
|
pushPopLock.lock();
|
||||||
try {
|
try {
|
||||||
EventQueue toPush = this;
|
EventQueue topQueue = this;
|
||||||
while (toPush.nextQueue != null) {
|
while (topQueue.nextQueue != null) {
|
||||||
toPush = toPush.nextQueue;
|
topQueue = topQueue.nextQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((topQueue.dispatchThread != null) &&
|
||||||
|
(topQueue.dispatchThread.getEventQueue() == this))
|
||||||
|
{
|
||||||
|
newEventQueue.dispatchThread = topQueue.dispatchThread;
|
||||||
|
topQueue.dispatchThread.setEventQueue(newEventQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer all events forward to new EventQueue.
|
// Transfer all events forward to new EventQueue.
|
||||||
while (toPush.peekEvent() != null) {
|
while (topQueue.peekEvent() != null) {
|
||||||
try {
|
try {
|
||||||
newEventQueue.postEventPrivate(toPush.getNextEvent());
|
// Use getNextEventPrivate() as it doesn't call flushPendingEvents()
|
||||||
|
newEventQueue.postEventPrivate(topQueue.getNextEventPrivate());
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
if (eventLog.isLoggable(PlatformLogger.FINE)) {
|
if (eventLog.isLoggable(PlatformLogger.FINE)) {
|
||||||
eventLog.fine("Interrupted push", ie);
|
eventLog.fine("Interrupted push", ie);
|
||||||
@ -777,28 +798,21 @@ public class EventQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newEventQueue.previousQueue = toPush;
|
// Wake up EDT waiting in getNextEvent(), so it can
|
||||||
|
// pick up a new EventQueue. Post the waking event before
|
||||||
|
// topQueue.nextQueue is assigned, otherwise the event would
|
||||||
|
// go newEventQueue
|
||||||
|
topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable));
|
||||||
|
|
||||||
/*
|
newEventQueue.previousQueue = topQueue;
|
||||||
* Stop the event dispatch thread associated with the currently
|
topQueue.nextQueue = newEventQueue;
|
||||||
* active event queue, so that after the new queue is pushed
|
|
||||||
* on the top this event dispatch thread won't prevent AWT from
|
|
||||||
* being automatically shut down.
|
|
||||||
* Use stopDispatchingLater() to avoid deadlock: stopDispatching()
|
|
||||||
* waits for the dispatch thread to exit, which in turn waits
|
|
||||||
* for the lock in EQ.detachDispatchThread(), which is hold by
|
|
||||||
* this method.
|
|
||||||
*/
|
|
||||||
if (toPush.dispatchThread != null) {
|
|
||||||
toPush.dispatchThread.stopDispatchingLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
toPush.nextQueue = newEventQueue;
|
|
||||||
|
|
||||||
AppContext appContext = AppContext.getAppContext();
|
AppContext appContext = AppContext.getAppContext();
|
||||||
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == toPush) {
|
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == topQueue) {
|
||||||
appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
|
appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pushPopCond.signalAll();
|
||||||
} finally {
|
} finally {
|
||||||
pushPopLock.unlock();
|
pushPopLock.unlock();
|
||||||
}
|
}
|
||||||
@ -822,44 +836,51 @@ public class EventQueue {
|
|||||||
eventLog.fine("EventQueue.pop(" + this + ")");
|
eventLog.fine("EventQueue.pop(" + this + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
EventDispatchThread dt = null;
|
|
||||||
pushPopLock.lock();
|
pushPopLock.lock();
|
||||||
try {
|
try {
|
||||||
EventQueue toPop = this;
|
EventQueue topQueue = this;
|
||||||
while (toPop.nextQueue != null) {
|
while (topQueue.nextQueue != null) {
|
||||||
toPop = toPop.nextQueue;
|
topQueue = topQueue.nextQueue;
|
||||||
}
|
}
|
||||||
EventQueue prev = toPop.previousQueue;
|
EventQueue prevQueue = topQueue.previousQueue;
|
||||||
if (prev == null) {
|
if (prevQueue == null) {
|
||||||
throw new EmptyStackException();
|
throw new EmptyStackException();
|
||||||
}
|
}
|
||||||
toPop.previousQueue = null;
|
|
||||||
|
topQueue.previousQueue = null;
|
||||||
|
prevQueue.nextQueue = null;
|
||||||
|
|
||||||
// Transfer all events back to previous EventQueue.
|
// Transfer all events back to previous EventQueue.
|
||||||
prev.nextQueue = null;
|
while (topQueue.peekEvent() != null) {
|
||||||
while (toPop.peekEvent() != null) {
|
|
||||||
try {
|
try {
|
||||||
prev.postEventPrivate(toPop.getNextEvent());
|
prevQueue.postEventPrivate(topQueue.getNextEventPrivate());
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
if (eventLog.isLoggable(PlatformLogger.FINE)) {
|
if (eventLog.isLoggable(PlatformLogger.FINE)) {
|
||||||
eventLog.fine("Interrupted pop", ie);
|
eventLog.fine("Interrupted pop", ie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((topQueue.dispatchThread != null) &&
|
||||||
|
(topQueue.dispatchThread.getEventQueue() == this))
|
||||||
|
{
|
||||||
|
prevQueue.dispatchThread = topQueue.dispatchThread;
|
||||||
|
topQueue.dispatchThread.setEventQueue(prevQueue);
|
||||||
|
}
|
||||||
|
|
||||||
AppContext appContext = AppContext.getAppContext();
|
AppContext appContext = AppContext.getAppContext();
|
||||||
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
|
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
|
||||||
appContext.put(AppContext.EVENT_QUEUE_KEY, prev);
|
appContext.put(AppContext.EVENT_QUEUE_KEY, prevQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
dt = toPop.dispatchThread;
|
// Wake up EDT waiting in getNextEvent(), so it can
|
||||||
|
// pick up a new EventQueue
|
||||||
|
topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable));
|
||||||
|
|
||||||
|
pushPopCond.signalAll();
|
||||||
} finally {
|
} finally {
|
||||||
pushPopLock.unlock();
|
pushPopLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dt != null) {
|
|
||||||
dt.stopDispatching(); // Must be done outside synchronized
|
|
||||||
// block to avoid possible deadlock
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -907,9 +928,9 @@ public class EventQueue {
|
|||||||
try {
|
try {
|
||||||
AppContext appContext = AppContext.getAppContext();
|
AppContext appContext = AppContext.getAppContext();
|
||||||
if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
|
if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
|
||||||
dispatchThread = (EventDispatchThread)
|
dispatchThread = AccessController.doPrivileged(
|
||||||
AccessController.doPrivileged(new PrivilegedAction() {
|
new PrivilegedAction<EventDispatchThread>() {
|
||||||
public Object run() {
|
public EventDispatchThread run() {
|
||||||
EventDispatchThread t =
|
EventDispatchThread t =
|
||||||
new EventDispatchThread(threadGroup,
|
new EventDispatchThread(threadGroup,
|
||||||
name,
|
name,
|
||||||
@ -919,7 +940,8 @@ public class EventQueue {
|
|||||||
t.setDaemon(false);
|
t.setDaemon(false);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
|
AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
|
||||||
dispatchThread.start();
|
dispatchThread.start();
|
||||||
}
|
}
|
||||||
@ -928,7 +950,7 @@ public class EventQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final void detachDispatchThread(EventDispatchThread edt, boolean restart) {
|
final boolean detachDispatchThread(EventDispatchThread edt) {
|
||||||
/*
|
/*
|
||||||
* This synchronized block is to secure that the event dispatch
|
* This synchronized block is to secure that the event dispatch
|
||||||
* thread won't die in the middle of posting a new event to the
|
* thread won't die in the middle of posting a new event to the
|
||||||
@ -939,26 +961,21 @@ public class EventQueue {
|
|||||||
*/
|
*/
|
||||||
pushPopLock.lock();
|
pushPopLock.lock();
|
||||||
try {
|
try {
|
||||||
EventDispatchThread oldDispatchThread = dispatchThread;
|
if (edt == dispatchThread) {
|
||||||
if (dispatchThread == edt) {
|
|
||||||
dispatchThread = null;
|
|
||||||
}
|
|
||||||
if (restart) {
|
|
||||||
/*
|
/*
|
||||||
* Event dispatch thread dies in case of an uncaught exception.
|
* Don't detach the thread if any events are pending. Not
|
||||||
* A new event dispatch thread for this queue will be started
|
* sure if it's a possible scenario, though.
|
||||||
* only if a new event is posted to it. In case if no more
|
|
||||||
* events are posted after this thread died all events that
|
|
||||||
* currently are in the queue will never be dispatched.
|
|
||||||
*
|
*
|
||||||
* Fix for 4648733. Check both the associated java event
|
* Fix for 4648733. Check both the associated java event
|
||||||
* queue and the PostEventQueue.
|
* queue and the PostEventQueue.
|
||||||
*/
|
*/
|
||||||
if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
|
if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
|
||||||
initDispatchThread();
|
return false;
|
||||||
}
|
}
|
||||||
AWTAutoShutdown.getInstance().notifyThreadFree(oldDispatchThread);
|
dispatchThread = null;
|
||||||
}
|
}
|
||||||
|
AWTAutoShutdown.getInstance().notifyThreadFree(edt);
|
||||||
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
pushPopLock.unlock();
|
pushPopLock.unlock();
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ import java.net.URL;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import sun.util.logging.PlatformLogger;
|
import sun.util.logging.PlatformLogger;
|
||||||
import sun.misc.SoftCache;
|
import sun.misc.SoftCache;
|
||||||
@ -592,7 +593,7 @@ public abstract class SunToolkit extends Toolkit
|
|||||||
}
|
}
|
||||||
PostEventQueue postEventQueue =
|
PostEventQueue postEventQueue =
|
||||||
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
|
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
|
||||||
if(postEventQueue != null) {
|
if (postEventQueue != null) {
|
||||||
postEventQueue.postEvent(event);
|
postEventQueue.postEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -610,18 +611,31 @@ public abstract class SunToolkit extends Toolkit
|
|||||||
postEvent(targetToAppContext(e.getSource()), pe);
|
postEvent(targetToAppContext(e.getSource()), pe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Lock flushLock = new ReentrantLock();
|
||||||
|
private static boolean isFlushingPendingEvents = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flush any pending events which haven't been posted to the AWT
|
* Flush any pending events which haven't been posted to the AWT
|
||||||
* EventQueue yet.
|
* EventQueue yet.
|
||||||
*/
|
*/
|
||||||
public static void flushPendingEvents() {
|
public static void flushPendingEvents() {
|
||||||
|
flushLock.lock();
|
||||||
|
try {
|
||||||
|
// Don't call flushPendingEvents() recursively
|
||||||
|
if (!isFlushingPendingEvents) {
|
||||||
|
isFlushingPendingEvents = true;
|
||||||
AppContext appContext = AppContext.getAppContext();
|
AppContext appContext = AppContext.getAppContext();
|
||||||
PostEventQueue postEventQueue =
|
PostEventQueue postEventQueue =
|
||||||
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
|
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
|
||||||
if(postEventQueue != null) {
|
if (postEventQueue != null) {
|
||||||
postEventQueue.flush();
|
postEventQueue.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
isFlushingPendingEvents = false;
|
||||||
|
flushLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isPostEventQueueEmpty() {
|
public static boolean isPostEventQueueEmpty() {
|
||||||
AppContext appContext = AppContext.getAppContext();
|
AppContext appContext = AppContext.getAppContext();
|
||||||
@ -1930,6 +1944,25 @@ public abstract class SunToolkit extends Toolkit
|
|||||||
return (Window)comp;
|
return (Window)comp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the system property indicated by the specified key.
|
||||||
|
*/
|
||||||
|
public static String getSystemProperty(final String key) {
|
||||||
|
return (String)AccessController.doPrivileged(new PrivilegedAction() {
|
||||||
|
public Object run() {
|
||||||
|
return System.getProperty(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the boolean value of the system property indicated by the specified key.
|
||||||
|
*/
|
||||||
|
protected static Boolean getBooleanSystemProperty(String key) {
|
||||||
|
return Boolean.valueOf(AccessController.
|
||||||
|
doPrivileged(new GetBooleanAction(key)));
|
||||||
|
}
|
||||||
|
|
||||||
private static Boolean sunAwtDisableMixing = null;
|
private static Boolean sunAwtDisableMixing = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1938,9 +1971,7 @@ public abstract class SunToolkit extends Toolkit
|
|||||||
*/
|
*/
|
||||||
public synchronized static boolean getSunAwtDisableMixing() {
|
public synchronized static boolean getSunAwtDisableMixing() {
|
||||||
if (sunAwtDisableMixing == null) {
|
if (sunAwtDisableMixing == null) {
|
||||||
sunAwtDisableMixing = Boolean.valueOf(
|
sunAwtDisableMixing = getBooleanSystemProperty("sun.awt.disableMixing");
|
||||||
AccessController.doPrivileged(
|
|
||||||
new GetBooleanAction("sun.awt.disableMixing")));
|
|
||||||
}
|
}
|
||||||
return sunAwtDisableMixing.booleanValue();
|
return sunAwtDisableMixing.booleanValue();
|
||||||
}
|
}
|
||||||
@ -2079,12 +2110,14 @@ class PostEventQueue {
|
|||||||
eventQueue = eq;
|
eventQueue = eq;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean noEvents() {
|
public synchronized boolean noEvents() {
|
||||||
return queueHead == null;
|
return queueHead == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Continually post pending AWTEvents to the Java EventQueue.
|
* Continually post pending AWTEvents to the Java EventQueue. The method
|
||||||
|
* is synchronized to ensure the flush is completed before a new event
|
||||||
|
* can be posted to this queue.
|
||||||
*/
|
*/
|
||||||
public synchronized void flush() {
|
public synchronized void flush() {
|
||||||
EventQueueItem tempQueue = queueHead;
|
EventQueueItem tempQueue = queueHead;
|
||||||
|
@ -1053,10 +1053,28 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
|
|||||||
return peer;
|
return peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Boolean sunAwtDisableGtkFileDialogs = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of "sun.awt.disableGtkFileDialogs" property. Default
|
||||||
|
* value is {@code false}.
|
||||||
|
*/
|
||||||
|
public synchronized static boolean getSunAwtDisableGtkFileDialogs() {
|
||||||
|
if (sunAwtDisableGtkFileDialogs == null) {
|
||||||
|
sunAwtDisableGtkFileDialogs =
|
||||||
|
getBooleanSystemProperty("sun.awt.disableGtkFileDialogs");
|
||||||
|
}
|
||||||
|
return sunAwtDisableGtkFileDialogs.booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
public FileDialogPeer createFileDialog(FileDialog target) {
|
public FileDialogPeer createFileDialog(FileDialog target) {
|
||||||
|
FileDialogPeer peer = null;
|
||||||
// The current GtkFileChooser is available from GTK+ 2.4
|
// The current GtkFileChooser is available from GTK+ 2.4
|
||||||
FileDialogPeer peer = checkGtkVersion(2, 4, 0) ? new GtkFileDialogPeer(
|
if (!getSunAwtDisableGtkFileDialogs() && checkGtkVersion(2, 4, 0)) {
|
||||||
target) : new XFileDialogPeer(target);
|
peer = new GtkFileDialogPeer(target);
|
||||||
|
} else {
|
||||||
|
peer = new XFileDialogPeer(target);
|
||||||
|
}
|
||||||
targetCreatedPeer(target, peer);
|
targetCreatedPeer(target, peer);
|
||||||
return peer;
|
return peer;
|
||||||
}
|
}
|
||||||
@ -1201,14 +1219,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getSystemProperty(final String name) {
|
|
||||||
return (String)AccessController.doPrivileged(new PrivilegedAction() {
|
|
||||||
public Object run() {
|
|
||||||
return System.getProperty(name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public PrintJob getPrintJob(final Frame frame, final String doctitle,
|
public PrintJob getPrintJob(final Frame frame, final String doctitle,
|
||||||
final Properties props) {
|
final Properties props) {
|
||||||
|
|
||||||
|
@ -778,8 +778,8 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
|
|||||||
x, y,
|
x, y,
|
||||||
xbe.get_x_root(),
|
xbe.get_x_root(),
|
||||||
xbe.get_y_root(),
|
xbe.get_y_root(),
|
||||||
clickCount,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
|
1,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
|
||||||
3,button==4 ? -1 : 1);
|
3,button==4 ? -1*clickCount : 1*clickCount);
|
||||||
postEventToEventQueue(mwe);
|
postEventToEventQueue(mwe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,29 @@ static gboolean filenameFilterCallback(const GtkFileFilterInfo * filter_info, gp
|
|||||||
filename);
|
filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void quit(gboolean isSignalHandler)
|
||||||
|
{
|
||||||
|
if (dialog != NULL)
|
||||||
|
{
|
||||||
|
// Callbacks from GTK signals are made within the GTK lock
|
||||||
|
// So, within a signal handler there is no need to call
|
||||||
|
// gdk_threads_enter() / fp_gdk_threads_leave()
|
||||||
|
if (!isSignalHandler) {
|
||||||
|
fp_gdk_threads_enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
fp_gtk_widget_hide (dialog);
|
||||||
|
fp_gtk_widget_destroy (dialog);
|
||||||
|
|
||||||
|
fp_gtk_main_quit ();
|
||||||
|
dialog = NULL;
|
||||||
|
|
||||||
|
if (!isSignalHandler) {
|
||||||
|
fp_gdk_threads_leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: sun_awt_X11_GtkFileDialogPeer
|
* Class: sun_awt_X11_GtkFileDialogPeer
|
||||||
* Method: quit
|
* Method: quit
|
||||||
@ -50,18 +73,7 @@ static gboolean filenameFilterCallback(const GtkFileFilterInfo * filter_info, gp
|
|||||||
JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
|
JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
|
||||||
(JNIEnv * env, jobject jpeer)
|
(JNIEnv * env, jobject jpeer)
|
||||||
{
|
{
|
||||||
if (dialog != NULL)
|
quit(FALSE);
|
||||||
{
|
|
||||||
fp_gdk_threads_enter();
|
|
||||||
|
|
||||||
fp_gtk_widget_hide (dialog);
|
|
||||||
fp_gtk_widget_destroy (dialog);
|
|
||||||
|
|
||||||
fp_gtk_main_quit ();
|
|
||||||
dialog = NULL;
|
|
||||||
|
|
||||||
fp_gdk_threads_leave();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,7 +159,7 @@ static void handle_response(GtkWidget* aDialog, gint responseId, gpointer obj)
|
|||||||
jfilenames);
|
jfilenames);
|
||||||
fp_g_free(current_folder);
|
fp_g_free(current_folder);
|
||||||
|
|
||||||
Java_sun_awt_X11_GtkFileDialogPeer_quit(NULL, NULL);
|
quit(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,3 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@test
|
@test
|
||||||
@bug 6304473 6727884
|
@bug 6304473 6727884
|
||||||
|
@ -34,35 +34,40 @@
|
|||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import java.lang.Math;
|
|
||||||
|
import sun.awt.SunToolkit;
|
||||||
|
|
||||||
import test.java.awt.regtesthelpers.Util;
|
import test.java.awt.regtesthelpers.Util;
|
||||||
|
|
||||||
public class LoopRobustness {
|
public class LoopRobustness {
|
||||||
static int clicks = 0;
|
|
||||||
final static long TIMEOUT = 5000;
|
final static long TIMEOUT = 5000;
|
||||||
final static Object LOCK = new Object();
|
final static Object LOCK = new Object();
|
||||||
static volatile boolean notifyOccur = false;
|
|
||||||
|
|
||||||
public static void main(String [] args) {
|
public static int clicks = 0;
|
||||||
|
public static volatile boolean notifyOccured = false;
|
||||||
|
public static volatile boolean otherExceptionsCaught = false;
|
||||||
|
|
||||||
|
public static void main(String [] args) throws Exception {
|
||||||
ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
|
ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
|
||||||
|
|
||||||
long at;
|
long at;
|
||||||
//wait for a TIMEOUT giving a chance to a new Thread above to accomplish its stuff.
|
//wait for a TIMEOUT giving a chance to a new Thread above to accomplish its stuff.
|
||||||
synchronized (LoopRobustness.LOCK){
|
synchronized (LoopRobustness.LOCK) {
|
||||||
new Thread(new TestThreadGroup(mainThreadGroup, "TestGroup"), new Impl()).start();
|
new Thread(new TestThreadGroup(mainThreadGroup, "TestGroup"), new Impl()).start();
|
||||||
at = System.currentTimeMillis();
|
at = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
while(!notifyOccur && System.currentTimeMillis() - at < TIMEOUT) {
|
while (!notifyOccured && (System.currentTimeMillis() - at < TIMEOUT)) {
|
||||||
LoopRobustness.LOCK.wait(1000);
|
LoopRobustness.LOCK.wait(1000);
|
||||||
}
|
}
|
||||||
} catch(InterruptedException e){
|
} catch (InterruptedException e) {
|
||||||
throw new RuntimeException("Test interrupted.", e);
|
throw new RuntimeException("Test interrupted.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !notifyOccur){
|
if (!notifyOccured) {
|
||||||
//notify doesn't occur after a reasonable time.
|
//notify doesn't occur after a reasonable time.
|
||||||
throw new RuntimeException("Test failed. Second Thread didn't notify MainThread.");
|
throw new RuntimeException("Test FAILED: second thread hasn't notified MainThread");
|
||||||
}
|
}
|
||||||
|
|
||||||
//now wait for two clicks
|
//now wait for two clicks
|
||||||
@ -75,7 +80,10 @@ public class LoopRobustness {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (clicks != 2) {
|
if (clicks != 2) {
|
||||||
throw new RuntimeException("robot should press button twice");
|
throw new RuntimeException("Test FAILED: robot should press button twice");
|
||||||
|
}
|
||||||
|
if (otherExceptionsCaught) {
|
||||||
|
throw new RuntimeException("Test FAILED: unexpected exceptions caught");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,18 +91,11 @@ public class LoopRobustness {
|
|||||||
class Impl implements Runnable{
|
class Impl implements Runnable{
|
||||||
static Robot robot;
|
static Robot robot;
|
||||||
public void run() {
|
public void run() {
|
||||||
|
SunToolkit.createNewAppContext();
|
||||||
|
|
||||||
Button b = new Button("Press me to test the AWT-Event Queue thread");
|
Button b = new Button("Press me to test the AWT-Event Queue thread");
|
||||||
Frame lr = new Frame("ROBUST FRAME");
|
Frame lr = new Frame("ROBUST FRAME");
|
||||||
/* Must load Toolkit on this thread only, rather then on Main.
|
|
||||||
If load on Main (on the parent ThreadGroup of current ThreadGroup) then
|
|
||||||
EDT will be created on Main thread and supplied with it's own exceptionHandler,
|
|
||||||
which just throws an Exception and terminates current thread.
|
|
||||||
The test implies that EDT is created on the child ThreadGroup (testThreadGroup)
|
|
||||||
which is supplied with its own uncaughtException().
|
|
||||||
*/
|
|
||||||
Toolkit.getDefaultToolkit();
|
|
||||||
lr.setBounds(100, 100, 300, 100);
|
lr.setBounds(100, 100, 300, 100);
|
||||||
|
|
||||||
b.addActionListener(new ActionListener() {
|
b.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
LoopRobustness.clicks++;
|
LoopRobustness.clicks++;
|
||||||
@ -107,40 +108,46 @@ class Impl implements Runnable{
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
robot = new Robot();
|
robot = new Robot();
|
||||||
} catch(AWTException e){
|
} catch (AWTException e) {
|
||||||
throw new RuntimeException("Test interrupted.", e);
|
throw new RuntimeException("Test interrupted.", e);
|
||||||
}
|
}
|
||||||
Util.waitForIdle(robot);
|
Util.waitForIdle(robot);
|
||||||
|
|
||||||
synchronized (LoopRobustness.LOCK){
|
synchronized (LoopRobustness.LOCK){
|
||||||
LoopRobustness.LOCK.notify();
|
LoopRobustness.LOCK.notify();
|
||||||
LoopRobustness.notifyOccur = true;
|
LoopRobustness.notifyOccured = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(i < 2){
|
while (i < 2) {
|
||||||
robot.mouseMove(b.getLocationOnScreen().x + b.getWidth()/2,
|
robot.mouseMove(b.getLocationOnScreen().x + b.getWidth()/2,
|
||||||
b.getLocationOnScreen().y + b.getHeight()/2 );
|
b.getLocationOnScreen().y + b.getHeight()/2);
|
||||||
|
Util.waitForIdle(robot);
|
||||||
robot.mousePress(InputEvent.BUTTON1_MASK);
|
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||||
// robot.delay(10);
|
Util.waitForIdle(robot);
|
||||||
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||||
|
Util.waitForIdle(robot);
|
||||||
i++;
|
i++;
|
||||||
robot.delay(1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestThreadGroup extends ThreadGroup {
|
class TestThreadGroup extends ThreadGroup {
|
||||||
TestThreadGroup(ThreadGroup threadGroup, String name){
|
TestThreadGroup(ThreadGroup threadGroup, String name) {
|
||||||
super(threadGroup, name);
|
super(threadGroup, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void uncaughtException(Thread exitedThread, Throwable e) {
|
public void uncaughtException(Thread thread, Throwable e) {
|
||||||
e.printStackTrace();
|
System.out.println("Exception caught: " + e);
|
||||||
if ((e instanceof ExceptionInInitializerError) || (e instanceof
|
e.printStackTrace(System.out);
|
||||||
NoClassDefFoundError)){
|
System.out.flush();
|
||||||
throw new RuntimeException("Test failed: other Exceptions were thrown ", e);
|
if ((e instanceof ExceptionInInitializerError) ||
|
||||||
|
(e instanceof NoClassDefFoundError))
|
||||||
|
{
|
||||||
|
// These two are expected
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
LoopRobustness.otherExceptionsCaught = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@test
|
||||||
|
@bug 6424157
|
||||||
|
@author Artem Ananiev: area=eventqueue
|
||||||
|
@run main PreserveDispatchThread
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
|
||||||
|
public class PreserveDispatchThread {
|
||||||
|
|
||||||
|
private static volatile Frame f;
|
||||||
|
private static volatile Dialog d;
|
||||||
|
|
||||||
|
private static volatile boolean isEDT = true;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
f = new Frame("F");
|
||||||
|
f.setSize(320, 340);
|
||||||
|
f.setLocationRelativeTo(null);
|
||||||
|
f.setVisible(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
test1();
|
||||||
|
if (!isEDT) {
|
||||||
|
throw new RuntimeException("Test FAILED (test1): event dispatch thread is changed");
|
||||||
|
}
|
||||||
|
|
||||||
|
test2();
|
||||||
|
if (!isEDT) {
|
||||||
|
throw new RuntimeException("Test FAILED (test2): event dispatch thread is changed");
|
||||||
|
}
|
||||||
|
|
||||||
|
test3();
|
||||||
|
if (!isEDT) {
|
||||||
|
throw new RuntimeException("Test FAILED (test3): event dispatch thread is changed");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (d != null) {
|
||||||
|
d.dispose();
|
||||||
|
}
|
||||||
|
f.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests that push/pop doesn't change the dispatch thread if
|
||||||
|
* called on EDT.
|
||||||
|
*/
|
||||||
|
private static void test1() throws Exception {
|
||||||
|
EventQueue.invokeAndWait(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
TestEventQueue teq = new TestEventQueue();
|
||||||
|
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
|
||||||
|
try {
|
||||||
|
seq.push(teq);
|
||||||
|
d = new TestDialog();
|
||||||
|
d.setVisible(true);
|
||||||
|
checkEDT();
|
||||||
|
} finally {
|
||||||
|
teq.pop();
|
||||||
|
}
|
||||||
|
checkEDT();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tests that push/pop doesn't change the dispatch thread if
|
||||||
|
* called on the main thread.
|
||||||
|
*/
|
||||||
|
private static void test2() throws Exception {
|
||||||
|
TestEventQueue teq = new TestEventQueue();
|
||||||
|
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
|
||||||
|
try {
|
||||||
|
seq.push(teq);
|
||||||
|
EventQueue.invokeAndWait(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
checkEDT();
|
||||||
|
d = new TestDialog();
|
||||||
|
d.setVisible(true);
|
||||||
|
checkEDT();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
teq.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Object test3Lock = new Object();
|
||||||
|
private static boolean test3Sync = false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A complex test: several nested invokeLater() are called and
|
||||||
|
* in every runnable a check for EDT is performed. At the ent
|
||||||
|
* of the test we wait for all the runnables to be processed
|
||||||
|
* and the dialog is disposed; otherwise the last EDT check can
|
||||||
|
* be later than this method returns and the whole test is passed.
|
||||||
|
*/
|
||||||
|
private static void test3() throws Exception {
|
||||||
|
EventQueue.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
d = new Dialog(f, true);
|
||||||
|
d.setSize(240, 180);
|
||||||
|
d.setLocationRelativeTo(f);
|
||||||
|
EventQueue.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
d.setVisible(true);
|
||||||
|
checkEDT();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
EventQueue.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
TestEventQueue teq = new TestEventQueue();
|
||||||
|
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
|
||||||
|
try {
|
||||||
|
seq.push(teq);
|
||||||
|
checkEDT();
|
||||||
|
EventQueue.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
d.dispose();
|
||||||
|
checkEDT();
|
||||||
|
synchronized (test3Lock) {
|
||||||
|
test3Sync = true;
|
||||||
|
test3Lock.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
teq.pop();
|
||||||
|
}
|
||||||
|
checkEDT();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
checkEDT();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
synchronized (test3Lock) {
|
||||||
|
while (!test3Sync) {
|
||||||
|
try {
|
||||||
|
test3Lock.wait();
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Make sure all the nested invokeLater/invokeAndWait are processed
|
||||||
|
EventQueue.invokeAndWait(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkEDT() {
|
||||||
|
isEDT = isEDT && EventQueue.isDispatchThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestEventQueue extends EventQueue {
|
||||||
|
public TestEventQueue() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
public void pop() {
|
||||||
|
super.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestDialog extends Dialog {
|
||||||
|
private volatile boolean dialogShown = false;
|
||||||
|
private volatile boolean paintCalled = false;
|
||||||
|
public TestDialog() {
|
||||||
|
super(f, true);
|
||||||
|
setSize(240, 180);
|
||||||
|
setLocationRelativeTo(f);
|
||||||
|
addComponentListener(new ComponentAdapter() {
|
||||||
|
@Override
|
||||||
|
public void componentShown(ComponentEvent e) {
|
||||||
|
if (paintCalled) {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
dialogShown = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void paint(Graphics g) {
|
||||||
|
if (dialogShown) {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
paintCalled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -43,6 +43,7 @@ public class PushPopTest {
|
|||||||
Runnable dummy = new Runnable() {
|
Runnable dummy = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
System.err.println("Dummy is here.");
|
System.err.println("Dummy is here.");
|
||||||
|
System.err.flush();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
|
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
|
||||||
@ -58,10 +59,11 @@ public class PushPopTest {
|
|||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
System.err.println("Dummy from SunToolkit");
|
System.err.println("Dummy from SunToolkit");
|
||||||
|
System.err.flush();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
InvocationEvent ie = new InvocationEvent(eq2, runnable, null, false);
|
InvocationEvent ie = new InvocationEvent(eq2, runnable, null, false);
|
||||||
System.err.println(ie);
|
// System.err.println(ie);
|
||||||
SunToolkit.postEvent(SunToolkit.targetToAppContext(frame), ie);
|
SunToolkit.postEvent(SunToolkit.targetToAppContext(frame), ie);
|
||||||
eq1.pop();
|
eq1.pop();
|
||||||
frame.dispose();
|
frame.dispose();
|
||||||
@ -70,14 +72,14 @@ public class PushPopTest {
|
|||||||
|
|
||||||
class MyEventQueue1 extends EventQueue {
|
class MyEventQueue1 extends EventQueue {
|
||||||
|
|
||||||
public void pop() throws EmptyStackException {
|
public void pop() {
|
||||||
super.pop();
|
super.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyEventQueue2 extends EventQueue {
|
class MyEventQueue2 extends EventQueue {
|
||||||
|
|
||||||
protected void pop() throws EmptyStackException {
|
protected void pop() {
|
||||||
System.err.println("pop2()");
|
System.err.println("pop2()");
|
||||||
Thread.dumpStack();
|
Thread.dumpStack();
|
||||||
try {
|
try {
|
||||||
@ -85,7 +87,8 @@ class MyEventQueue2 extends EventQueue {
|
|||||||
public void run() {
|
public void run() {
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
System.err.println("Dummy from here");
|
System.err.println("Dummy from pop");
|
||||||
|
System.err.flush();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
InvocationEvent ie = new InvocationEvent(MyEventQueue2.this, runnable, null, false);
|
InvocationEvent ie = new InvocationEvent(MyEventQueue2.this, runnable, null, false);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user