275 * @see #getTitle() |
275 * @see #getTitle() |
276 * @see #setTitle(String) |
276 * @see #setTitle(String) |
277 */ |
277 */ |
278 String title; |
278 String title; |
279 |
279 |
280 private transient volatile boolean keepBlockingEDT = false; |
|
281 private transient volatile boolean keepBlockingCT = false; |
|
282 |
|
283 private transient ModalEventFilter modalFilter; |
280 private transient ModalEventFilter modalFilter; |
|
281 private transient volatile SecondaryLoop secondaryLoop; |
284 |
282 |
285 /* |
283 /* |
286 * Indicates that this dialog is being hidden. This flag is set to true at |
284 * Indicates that this dialog is being hidden. This flag is set to true at |
287 * the beginning of hide() and to false at the end of hide(). |
285 * the beginning of hide() and to false at the end of hide(). |
288 * |
286 * |
1003 */ |
1001 */ |
1004 public void setVisible(boolean b) { |
1002 public void setVisible(boolean b) { |
1005 super.setVisible(b); |
1003 super.setVisible(b); |
1006 } |
1004 } |
1007 |
1005 |
1008 /** |
|
1009 * Stores the app context on which event dispatch thread the dialog |
|
1010 * is being shown. Initialized in show(), used in hideAndDisposeHandler() |
|
1011 */ |
|
1012 transient private AppContext showAppContext; |
|
1013 |
|
1014 /** |
1006 /** |
1015 * Makes the {@code Dialog} visible. If the dialog and/or its owner |
1007 * Makes the {@code Dialog} visible. If the dialog and/or its owner |
1016 * are not yet displayable, both are made displayable. The |
1008 * are not yet displayable, both are made displayable. The |
1017 * dialog will be validated prior to being made visible. |
1009 * dialog will be validated prior to being made visible. |
1018 * If the dialog is already visible, this will bring the dialog |
1010 * If the dialog is already visible, this will bring the dialog |
1035 public void show() { |
1027 public void show() { |
1036 beforeFirstShow = false; |
1028 beforeFirstShow = false; |
1037 if (!isModal()) { |
1029 if (!isModal()) { |
1038 conditionalShow(null, null); |
1030 conditionalShow(null, null); |
1039 } else { |
1031 } else { |
1040 // Set this variable before calling conditionalShow(). That |
1032 AppContext showAppContext = AppContext.getAppContext(); |
1041 // way, if the Dialog is hidden right after being shown, we |
|
1042 // won't mistakenly block this thread. |
|
1043 keepBlockingEDT = true; |
|
1044 keepBlockingCT = true; |
|
1045 |
|
1046 // Store the app context on which this dialog is being shown. |
|
1047 // Event dispatch thread of this app context will be sleeping until |
|
1048 // we wake it by any event from hideAndDisposeHandler(). |
|
1049 showAppContext = AppContext.getAppContext(); |
|
1050 |
1033 |
1051 AtomicLong time = new AtomicLong(); |
1034 AtomicLong time = new AtomicLong(); |
1052 Component predictedFocusOwner = null; |
1035 Component predictedFocusOwner = null; |
1053 try { |
1036 try { |
1054 predictedFocusOwner = getMostRecentFocusOwner(); |
1037 predictedFocusOwner = getMostRecentFocusOwner(); |
1055 if (conditionalShow(predictedFocusOwner, time)) { |
1038 if (conditionalShow(predictedFocusOwner, time)) { |
1056 // We have two mechanisms for blocking: 1. If we're on the |
|
1057 // EventDispatchThread, start a new event pump. 2. If we're |
|
1058 // on any other thread, call wait() on the treelock. |
|
1059 |
|
1060 modalFilter = ModalEventFilter.createFilterForDialog(this); |
1039 modalFilter = ModalEventFilter.createFilterForDialog(this); |
1061 |
1040 Conditional cond = new Conditional() { |
1062 final Runnable pumpEventsForFilter = new Runnable() { |
1041 @Override |
1063 public void run() { |
1042 public boolean evaluate() { |
1064 EventDispatchThread dispatchThread = |
1043 return windowClosingException == null; |
1065 (EventDispatchThread)Thread.currentThread(); |
|
1066 dispatchThread.pumpEventsForFilter(new Conditional() { |
|
1067 public boolean evaluate() { |
|
1068 synchronized (getTreeLock()) { |
|
1069 return keepBlockingEDT && windowClosingException == null; |
|
1070 } |
|
1071 } |
|
1072 }, modalFilter); |
|
1073 } |
1044 } |
1074 }; |
1045 }; |
1075 |
1046 |
1076 // if this dialog is toolkit-modal, the filter should be added |
1047 // if this dialog is toolkit-modal, the filter should be added |
1077 // to all EDTs (for all AppContexts) |
1048 // to all EDTs (for all AppContexts) |
1094 } |
1065 } |
1095 } |
1066 } |
1096 |
1067 |
1097 modalityPushed(); |
1068 modalityPushed(); |
1098 try { |
1069 try { |
1099 if (EventQueue.isDispatchThread()) { |
1070 EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); |
1100 /* |
1071 secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 5000); |
1101 * dispose SequencedEvent we are dispatching on current |
1072 if (!secondaryLoop.enter()) { |
1102 * AppContext, to prevent us from hang. |
1073 secondaryLoop = null; |
1103 * |
|
1104 */ |
|
1105 // BugId 4531693 (son@sparc.spb.su) |
|
1106 SequencedEvent currentSequencedEvent = KeyboardFocusManager. |
|
1107 getCurrentKeyboardFocusManager().getCurrentSequencedEvent(); |
|
1108 if (currentSequencedEvent != null) { |
|
1109 currentSequencedEvent.dispose(); |
|
1110 } |
|
1111 |
|
1112 /* |
|
1113 * Event processing is done inside doPrivileged block so that |
|
1114 * it wouldn't matter even if user code is on the stack |
|
1115 * Fix for BugId 6300270 |
|
1116 */ |
|
1117 |
|
1118 AccessController.doPrivileged(new PrivilegedAction() { |
|
1119 public Object run() { |
|
1120 pumpEventsForFilter.run(); |
|
1121 return null; |
|
1122 } |
|
1123 }); |
|
1124 } else { |
|
1125 synchronized (getTreeLock()) { |
|
1126 Toolkit.getEventQueue().postEvent(new PeerEvent(this, |
|
1127 pumpEventsForFilter, |
|
1128 PeerEvent.PRIORITY_EVENT)); |
|
1129 while (keepBlockingCT && windowClosingException == null) { |
|
1130 try { |
|
1131 getTreeLock().wait(); |
|
1132 } catch (InterruptedException e) { |
|
1133 break; |
|
1134 } |
|
1135 } |
|
1136 } |
|
1137 } |
1074 } |
1138 } finally { |
1075 } finally { |
1139 modalityPopped(); |
1076 modalityPopped(); |
1140 } |
1077 } |
1141 |
1078 |
1192 windowClosingException.fillInStackTrace(); |
1129 windowClosingException.fillInStackTrace(); |
1193 windowClosingException.printStackTrace(); |
1130 windowClosingException.printStackTrace(); |
1194 windowClosingException = null; |
1131 windowClosingException = null; |
1195 } |
1132 } |
1196 } |
1133 } |
1197 final class WakingRunnable implements Runnable { |
1134 |
1198 public void run() { |
|
1199 synchronized (getTreeLock()) { |
|
1200 keepBlockingCT = false; |
|
1201 getTreeLock().notifyAll(); |
|
1202 } |
|
1203 } |
|
1204 } |
|
1205 private void hideAndDisposePreHandler() { |
1135 private void hideAndDisposePreHandler() { |
1206 isInHide = true; |
1136 isInHide = true; |
1207 synchronized (getTreeLock()) { |
1137 synchronized (getTreeLock()) { |
1208 if (keepBlockingEDT) { |
1138 if (secondaryLoop != null) { |
1209 modalHide(); |
1139 modalHide(); |
1210 // dialog can be shown and then disposed before its |
1140 // dialog can be shown and then disposed before its |
1211 // modal filter is created |
1141 // modal filter is created |
1212 if (modalFilter != null) { |
1142 if (modalFilter != null) { |
1213 modalFilter.disable(); |
1143 modalFilter.disable(); |
1215 modalDialogs.remove(this); |
1145 modalDialogs.remove(this); |
1216 } |
1146 } |
1217 } |
1147 } |
1218 } |
1148 } |
1219 private void hideAndDisposeHandler() { |
1149 private void hideAndDisposeHandler() { |
1220 synchronized (getTreeLock()) { |
1150 if (secondaryLoop != null) { |
1221 if (keepBlockingEDT) { |
1151 secondaryLoop.exit(); |
1222 keepBlockingEDT = false; |
1152 secondaryLoop = null; |
1223 PeerEvent wakingEvent = new PeerEvent(getToolkit(), new WakingRunnable(), PeerEvent.PRIORITY_EVENT); |
|
1224 AppContext curAppContext = AppContext.getAppContext(); |
|
1225 if (showAppContext != curAppContext) { |
|
1226 // Wake up event dispatch thread on which the dialog was |
|
1227 // initially shown |
|
1228 SunToolkit.postEvent(showAppContext, wakingEvent); |
|
1229 showAppContext = null; |
|
1230 } else { |
|
1231 Toolkit.getEventQueue().postEvent(wakingEvent); |
|
1232 } |
|
1233 } |
|
1234 } |
1153 } |
1235 isInHide = false; |
1154 isInHide = false; |
1236 } |
1155 } |
1237 |
1156 |
1238 /** |
1157 /** |