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) {