提交 3403002c 编写于 作者: L lana

Merge

...@@ -61,77 +61,31 @@ import sun.awt.EventQueueDelegate; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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; ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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,17 +42,16 @@ static gboolean filenameFilterCallback(const GtkFileFilterInfo * filter_info, gp ...@@ -42,17 +42,16 @@ static gboolean filenameFilterCallback(const GtkFileFilterInfo * filter_info, gp
filename); filename);
} }
/* static void quit(gboolean isSignalHandler)
* Class: sun_awt_X11_GtkFileDialogPeer
* Method: quit
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
(JNIEnv * env, jobject jpeer)
{ {
if (dialog != NULL) 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_gdk_threads_enter();
}
fp_gtk_widget_hide (dialog); fp_gtk_widget_hide (dialog);
fp_gtk_widget_destroy (dialog); fp_gtk_widget_destroy (dialog);
...@@ -60,8 +59,21 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit ...@@ -60,8 +59,21 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
fp_gtk_main_quit (); fp_gtk_main_quit ();
dialog = NULL; dialog = NULL;
if (!isSignalHandler) {
fp_gdk_threads_leave(); fp_gdk_threads_leave();
} }
}
}
/*
* Class: sun_awt_X11_GtkFileDialogPeer
* Method: quit
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
(JNIEnv * env, jobject jpeer)
{
quit(FALSE);
} }
/** /**
...@@ -147,7 +159,7 @@ static void handle_response(GtkWidget* aDialog, gint responseId, gpointer obj) ...@@ -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);
} }
/* /*
......
/*
* 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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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{ ...@@ -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;
} }
} }
......
/*
* 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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册