Bug 431287 - [SWT_AWT] SWT_AWT hangs in a dialog under on OS X
diff --git a/bundles/org.eclipse.swt/Eclipse SWT AWT/cocoa/org/eclipse/swt/awt/SWT_AWT.java b/bundles/org.eclipse.swt/Eclipse SWT AWT/cocoa/org/eclipse/swt/awt/SWT_AWT.java
index a916eaf..2900d42 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT AWT/cocoa/org/eclipse/swt/awt/SWT_AWT.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT AWT/cocoa/org/eclipse/swt/awt/SWT_AWT.java
@@ -47,6 +47,11 @@
*/
static String EMBEDDED_FRAME_KEY = "org.eclipse.swt.awt.SWT_AWT.embeddedFrame";
+ /**
+ * Key for running pending AWT invokeLater() events.
+ */
+ static final String RUN_AWT_INVOKE_LATER_KEY = "org.eclipse.swt.internal.runAWTInvokeLater"; //$NON-NLS-1$
+
static {
System.setProperty("apple.awt.usingSWT", "true");
}
@@ -136,18 +141,18 @@
}
final long /*int*/ handle = parent.view.id;
-
- Class clazz = null;
+
+ final Class [] clazz = new Class [1];
try {
String className = embeddedFrameClass != null ? embeddedFrameClass : JDK16_FRAME;
if (embeddedFrameClass == null) {
- clazz = Class.forName(className, true, ClassLoader.getSystemClassLoader());
+ clazz[0] = Class.forName(className, true, ClassLoader.getSystemClassLoader());
} else {
- clazz = Class.forName(className);
+ clazz[0] = Class.forName(className);
}
} catch (ClassNotFoundException cne) {
try {
- clazz = Class.forName(JDK17_FRAME);
+ clazz[0] = Class.forName(JDK17_FRAME);
} catch (ClassNotFoundException cne1) {
SWT.error (SWT.ERROR_NOT_IMPLEMENTED, cne1);
}
@@ -155,18 +160,48 @@
SWT.error (SWT.ERROR_UNSPECIFIED , e, " [Error while starting AWT]");
}
+ /* NOTE: Swing must not be initialize in an invokeLater() or it hangs */
initializeSwing();
- Object value = null;
- Constructor constructor = null;
- try {
- constructor = clazz.getConstructor (new Class [] {long.class});
- value = constructor.newInstance (new Object [] {new Long(handle)});
- } catch (Throwable e) {
- SWT.error(SWT.ERROR_NOT_IMPLEMENTED, e);
+
+ final Frame [] result = new Frame [1];
+ final Throwable[] exception = new Throwable[1];
+ Runnable runnable = new Runnable () {
+ boolean run;
+ public void run() {
+ if (run) return;
+ run = true;
+ Constructor constructor = null;
+ try {
+ constructor = clazz[0].getConstructor (new Class [] {long.class});
+ result [0] = (Frame) (constructor.newInstance (new Object [] {new Long(handle)}));
+ result [0].addNotify();
+ } catch (Throwable e) {
+ exception[0] = e;
+ }
+ }
+ };
+ if (EventQueue.isDispatchThread() || parent.getDisplay().getSyncThread() != null) {
+ runnable.run();
+ } else {
+ /* Force AWT to process the invokeLater() right away */
+ EventQueue.invokeLater(runnable);
+ Display display = parent.getDisplay();
+ while (result[0] == null && exception[0] == null) {
+ display.setData(RUN_AWT_INVOKE_LATER_KEY, new Boolean (true));
+ Boolean invoked = (Boolean)display.getData(RUN_AWT_INVOKE_LATER_KEY);
+ if (invoked != null && !invoked.booleanValue()) {
+ runnable.run();
+ }
+ }
}
- final Frame frame = (Frame) value;
+ if (exception[0] != null) {
+ SWT.error (SWT.ERROR_NOT_IMPLEMENTED, exception[0]);
+ }
+ final Frame frame = result[0];
final boolean isJDK17 = JDK17_FRAME.equals(frame.getClass().getName());
- frame.addNotify();
+
+ /* NOTE: addNotify() should not be called in the UI thread or we could hang */
+ //frame.addNotify();
parent.setData(EMBEDDED_FRAME_KEY, frame);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java
index 381ad37..483001f 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java
@@ -122,6 +122,9 @@
Synchronizer synchronizer;
Thread thread;
boolean allowTimers = true, runAsyncMessages = true;
+
+ /* AWT Invoke Later */
+ static final String RUN_AWT_INVOKE_LATER_KEY = "org.eclipse.swt.internal.runAWTInvokeLater"; //$NON-NLS-1$
GCData[] contexts;
@@ -3978,6 +3981,18 @@
return synchronizer.runAsyncMessages (all);
}
+boolean runAWTInvokeLater() {
+ long /*int*/ cls = OS.objc_lookUpClass("JNFRunLoop");
+ if (cls == 0) return false;
+ long /*int*/ mode = OS.objc_msgSend(cls, OS.sel_javaRunLoopMode);
+ if (mode == 0) return false;
+ NSString javaRunLoopMode = new NSString(mode);
+ allowTimers = runAsyncMessages = false;
+ NSRunLoop.currentRunLoop().runMode(javaRunLoopMode, NSDate.distantFuture());
+ allowTimers = runAsyncMessages = true;
+ return true;
+}
+
boolean runContexts () {
if (contexts != null) {
for (int i = 0; i < contexts.length; i++) {
@@ -4445,6 +4460,12 @@
if (key.equals (LOCK_CURSOR)) {
lockCursor = ((Boolean)value).booleanValue ();
}
+
+ if (key.equals(RUN_AWT_INVOKE_LATER_KEY)) {
+ if (value != null) {
+ value = new Boolean (runAWTInvokeLater());
+ }
+ }
/* Remove the key/value pair */
if (value == null) {