mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-15 16:44:36 +02:00
8088132: [Swing, singleThread] ClassCastException in nested event loop when showing multiple message dialogs in SwingNode
Reviewed-by: serb
This commit is contained in:
parent
b8ca97f45c
commit
ebf03d174d
2 changed files with 90 additions and 9 deletions
|
@ -30,6 +30,8 @@ import java.awt.event.WindowEvent;
|
||||||
import java.awt.peer.ComponentPeer;
|
import java.awt.peer.ComponentPeer;
|
||||||
import java.awt.peer.LightweightPeer;
|
import java.awt.peer.LightweightPeer;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
@ -77,6 +79,8 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
|
||||||
private boolean consumeNextKeyTyped;
|
private boolean consumeNextKeyTyped;
|
||||||
private Component restoreFocusTo;
|
private Component restoreFocusTo;
|
||||||
|
|
||||||
|
private static boolean fxAppThreadIsDispatchThread;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
AWTAccessor.setDefaultKeyboardFocusManagerAccessor(
|
AWTAccessor.setDefaultKeyboardFocusManagerAccessor(
|
||||||
new AWTAccessor.DefaultKeyboardFocusManagerAccessor() {
|
new AWTAccessor.DefaultKeyboardFocusManagerAccessor() {
|
||||||
|
@ -84,6 +88,13 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
|
||||||
dkfm.consumeNextKeyTyped(e);
|
dkfm.consumeNextKeyTyped(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
public Object run() {
|
||||||
|
fxAppThreadIsDispatchThread =
|
||||||
|
"true".equals(System.getProperty("javafx.embed.singleThread"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TypeAheadMarker {
|
private static class TypeAheadMarker {
|
||||||
|
@ -264,6 +275,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
|
||||||
}
|
}
|
||||||
SunToolkit.postEvent(targetAppContext, se);
|
SunToolkit.postEvent(targetAppContext, se);
|
||||||
if (EventQueue.isDispatchThread()) {
|
if (EventQueue.isDispatchThread()) {
|
||||||
|
if (Thread.currentThread() instanceof EventDispatchThread) {
|
||||||
EventDispatchThread edt = (EventDispatchThread)
|
EventDispatchThread edt = (EventDispatchThread)
|
||||||
Thread.currentThread();
|
Thread.currentThread();
|
||||||
edt.pumpEvents(SentEvent.ID, new Conditional() {
|
edt.pumpEvents(SentEvent.ID, new Conditional() {
|
||||||
|
@ -271,6 +283,33 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager {
|
||||||
return !se.dispatched && !targetAppContext.isDisposed();
|
return !se.dispatched && !targetAppContext.isDisposed();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (fxAppThreadIsDispatchThread) {
|
||||||
|
Thread fxCheckDispatchThread = new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!se.dispatched && !targetAppContext.isDisposed()) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fxCheckDispatchThread.start();
|
||||||
|
try {
|
||||||
|
// check if event is dispatched or disposed
|
||||||
|
// but since this user app thread is same as
|
||||||
|
// dispatch thread in fx when run with
|
||||||
|
// javafx.embed.singleThread=true
|
||||||
|
// we do not wait infinitely to avoid deadlock
|
||||||
|
// as dispatch will ultimately be done by this thread
|
||||||
|
fxCheckDispatchThread.join(500);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
synchronized (se) {
|
synchronized (se) {
|
||||||
while (!se.dispatched && !targetAppContext.isDisposed()) {
|
while (!se.dispatched && !targetAppContext.isDisposed()) {
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
package java.awt;
|
package java.awt;
|
||||||
|
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import sun.awt.AWTAccessor;
|
import sun.awt.AWTAccessor;
|
||||||
import sun.awt.AppContext;
|
import sun.awt.AppContext;
|
||||||
|
@ -55,6 +57,8 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
|
||||||
private AppContext appContext;
|
private AppContext appContext;
|
||||||
private boolean disposed;
|
private boolean disposed;
|
||||||
|
|
||||||
|
private static boolean fxAppThreadIsDispatchThread;
|
||||||
|
private Thread fxCheckSequenceThread;
|
||||||
static {
|
static {
|
||||||
AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
|
AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
|
||||||
public AWTEvent getNested(AWTEvent sequencedEvent) {
|
public AWTEvent getNested(AWTEvent sequencedEvent) {
|
||||||
|
@ -68,6 +72,13 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
|
||||||
return new SequencedEvent(event);
|
return new SequencedEvent(event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||||
|
public Object run() {
|
||||||
|
fxAppThreadIsDispatchThread =
|
||||||
|
"true".equals(System.getProperty("javafx.embed.singleThread"));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,6 +94,21 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
|
||||||
// All AWTEvents that are wrapped in SequencedEvents are (at
|
// All AWTEvents that are wrapped in SequencedEvents are (at
|
||||||
// least currently) implicitly generated by the system
|
// least currently) implicitly generated by the system
|
||||||
SunToolkit.setSystemGenerated(nested);
|
SunToolkit.setSystemGenerated(nested);
|
||||||
|
|
||||||
|
if (fxAppThreadIsDispatchThread) {
|
||||||
|
fxCheckSequenceThread = new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while(!isFirstOrDisposed()) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
synchronized (SequencedEvent.class) {
|
synchronized (SequencedEvent.class) {
|
||||||
list.add(this);
|
list.add(this);
|
||||||
}
|
}
|
||||||
|
@ -106,6 +132,7 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
|
||||||
|
|
||||||
if (getFirst() != this) {
|
if (getFirst() != this) {
|
||||||
if (EventQueue.isDispatchThread()) {
|
if (EventQueue.isDispatchThread()) {
|
||||||
|
if (Thread.currentThread() instanceof EventDispatchThread) {
|
||||||
EventDispatchThread edt = (EventDispatchThread)
|
EventDispatchThread edt = (EventDispatchThread)
|
||||||
Thread.currentThread();
|
Thread.currentThread();
|
||||||
edt.pumpEvents(SentEvent.ID, new Conditional() {
|
edt.pumpEvents(SentEvent.ID, new Conditional() {
|
||||||
|
@ -113,6 +140,21 @@ class SequencedEvent extends AWTEvent implements ActiveEvent {
|
||||||
return !SequencedEvent.this.isFirstOrDisposed();
|
return !SequencedEvent.this.isFirstOrDisposed();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (fxAppThreadIsDispatchThread) {
|
||||||
|
fxCheckSequenceThread.start();
|
||||||
|
try {
|
||||||
|
// check if event is dispatched or disposed
|
||||||
|
// but since this user app thread is same as
|
||||||
|
// dispatch thread in fx when run with
|
||||||
|
// javafx.embed.singleThread=true
|
||||||
|
// we do not wait infinitely to avoid deadlock
|
||||||
|
// as dispatch will ultimately be done by this thread
|
||||||
|
fxCheckSequenceThread.join(500);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
while(!isFirstOrDisposed()) {
|
while(!isFirstOrDisposed()) {
|
||||||
synchronized (SequencedEvent.class) {
|
synchronized (SequencedEvent.class) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue