changeset 7871:d502cc7bcc3d

8006634: Unify LWCToolkit.invokeAndWait() and sun.awt.datatransfer.ToolkitThreadBlockedHandler Summary: Changed the logic for the nested event loops and deleted deadlock detection Reviewed-by: art, denis
author pchelko
date Mon, 25 Feb 2013 10:17:25 +0000
parents 63bb402d4a6a
children e58f0b163f43
files src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java src/macosx/native/sun/awt/AWTView.m src/macosx/native/sun/awt/ApplicationDelegate.m src/macosx/native/sun/awt/CClipboard.m src/macosx/native/sun/awt/CDropTarget.m src/macosx/native/sun/awt/CMenu.m src/macosx/native/sun/awt/CMenuBar.m src/macosx/native/sun/awt/CMenuItem.m src/macosx/native/sun/awt/JavaComponentAccessibility.m src/macosx/native/sun/awt/LWCToolkit.m src/macosx/native/sun/osxapp/ThreadUtilities.h src/macosx/native/sun/osxapp/ThreadUtilities.m
diffstat 14 files changed, 115 insertions(+), 268 deletions(-) [+]
line wrap: on
line diff
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Mon Feb 25 10:17:25 2013 +0000
@@ -30,6 +30,7 @@
 import java.awt.event.*;
 import java.awt.peer.WindowPeer;
 import java.beans.*;
+import java.lang.reflect.InvocationTargetException;
 import java.util.List;
 
 import javax.swing.*;
@@ -861,7 +862,16 @@
 
     private void flushBuffers() {
         if (isVisible() && !nativeBounds.isEmpty()) {
-            LWCToolkit.getLWCToolkit().flushPendingEventsOnAppkit(target);
+            try {
+                LWCToolkit.invokeAndWait(new Runnable() {
+                    @Override
+                    public void run() {
+                        //Posting an empty to flush the EventQueue without blocking the main thread
+                    }
+                }, target);
+            } catch (InterruptedException | InvocationTargetException e) {
+                e.printStackTrace();
+            }
         }
     }
 
--- a/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CToolkitThreadBlockedHandler.java	Mon Feb 25 10:17:25 2013 +0000
@@ -25,27 +25,33 @@
 
 package sun.lwawt.macosx;
 
+import sun.awt.Mutex;
 import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
 
-final class CToolkitThreadBlockedHandler implements ToolkitThreadBlockedHandler {
-    private final LWCToolkit toolkit = (LWCToolkit)java.awt.Toolkit.getDefaultToolkit();
+final class CToolkitThreadBlockedHandler extends Mutex implements ToolkitThreadBlockedHandler {
+    private long awtRunLoopMediator = 0;
+    private final boolean processEvents;
 
-    public void lock() {
-    }
-
-    public void unlock() {
-    }
-
-    protected boolean isOwned() {
-       return false;
+    CToolkitThreadBlockedHandler() {
+        super();
+        this.processEvents = true;
     }
 
     public void enter() {
-        // Execute the next AppKit event while we are waiting for system to
-        // finish our request - this will save us from biting our own tail
-        toolkit.executeNextAppKitEvent();
+        if (!isOwned()) {
+            throw new IllegalMonitorStateException();
+        }
+        awtRunLoopMediator = LWCToolkit.createAWTRunLoopMediator();
+        unlock();
+        LWCToolkit.doAWTRunLoop(awtRunLoopMediator, processEvents);
+        lock();
     }
 
     public void exit() {
+        if (!isOwned()) {
+            throw new IllegalMonitorStateException();
+        }
+        LWCToolkit.stopAWTRunLoop(awtRunLoopMediator);
+        awtRunLoopMediator = 0;
     }
 }
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Mon Feb 25 10:17:25 2013 +0000
@@ -63,8 +63,6 @@
 
     private static native void initIDs();
 
-    static native void executeNextAppKitEvent();
-
     private static CInputMethodDescriptor sInputMethodDescriptor;
 
     static {
@@ -502,30 +500,6 @@
         synchronized(ret) { return ret[0]; }
     }
 
-    /**
-     * Just a wrapper for LWCToolkit.invokeAndWait. Posts an empty event to the
-     * appropriate event queue and waits for it to finish.
-     */
-    public static void flushPendingEventsOnAppkit(final Component component) {
-        try {
-            invokeAndWait(new Runnable() {
-                @Override
-                public void run() {
-                }
-            }, component);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    // Kicks an event over to the appropriate eventqueue and waits for it to finish
-    // To avoid deadlocking, we manually run the NSRunLoop while waiting
-    // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop
-    // The CInvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop
-    public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException {
-        invokeAndWait(event, component, true);
-    }
-
     public static <T> T invokeAndWait(final Callable<T> callable, Component component) throws Exception {
         final CallableWrapper<T> wrapper = new CallableWrapper<T>(callable);
         invokeAndWait(wrapper, component);
@@ -555,10 +529,27 @@
         }
     }
 
-    public static void invokeAndWait(Runnable event, Component component, boolean detectDeadlocks) throws InterruptedException, InvocationTargetException {
-        long mediator = createAWTRunLoopMediator();
+    // Kicks an event over to the appropriate eventqueue and waits for it to finish
+    // To avoid deadlocking, we manually run the NSRunLoop while waiting
+    // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop
+    // The InvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop
+    // Does not dispatch native events while in the loop
+    public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException {
+        final long mediator = createAWTRunLoopMediator();
 
-        InvocationEvent invocationEvent = new CPeerEvent(event, mediator);
+        InvocationEvent invocationEvent =
+                new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event) {
+                    @Override
+                    public void dispatch() {
+                        try {
+                            super.dispatch();
+                        } finally {
+                            if (mediator != 0) {
+                                stopAWTRunLoop(mediator);
+                            }
+                        }
+                    }
+                };
 
         if (component != null) {
             AppContext appContext = SunToolkit.targetToAppContext(component);
@@ -571,7 +562,7 @@
             ((LWCToolkit)Toolkit.getDefaultToolkit()).getSystemEventQueueForInvokeAndWait().postEvent(invocationEvent);
         }
 
-        doAWTRunLoop(mediator, true, detectDeadlocks);
+        doAWTRunLoop(mediator, false);
 
         Throwable eventException = invocationEvent.getException();
         if (eventException != null) {
@@ -583,7 +574,8 @@
     }
 
     public static void invokeLater(Runnable event, Component component) throws InvocationTargetException {
-        final InvocationEvent invocationEvent = new CPeerEvent(event, 0);
+        final InvocationEvent invocationEvent =
+                new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event);
 
         if (component != null) {
             final AppContext appContext = SunToolkit.targetToAppContext(component);
@@ -688,31 +680,6 @@
         return false;
     }
 
-    // Extends PeerEvent because we want to pass long an ObjC mediator object and because we want these events to be posted early
-    // Typically, rather than relying on the notifier to call notifyAll(), we use the mediator to stop the runloop
-    public static class CPeerEvent extends PeerEvent {
-        private long _mediator = 0;
-
-        public CPeerEvent(Runnable runnable, long mediator) {
-            super(Toolkit.getDefaultToolkit(), runnable, null, true, 0);
-            _mediator = mediator;
-        }
-
-        public void dispatch() {
-            try {
-                super.dispatch();
-            } finally {
-                if (_mediator != 0) {
-                    LWCToolkit.stopAWTRunLoop(_mediator);
-                }
-            }
-        }
-    }
-
-    // Call through to native methods
-    public static void doAWTRunLoop(long mediator, boolean awtMode) { doAWTRunLoop(mediator, awtMode, true); }
-    public static void doAWTRunLoop(long mediator) { doAWTRunLoop(mediator, true); }
-
     private static Boolean sunAwtDisableCALayers = null;
 
     /**
@@ -737,12 +704,20 @@
      * Native methods section
      ************************/
 
-    // These are public because they are accessed from WebKitPluginObject in JavaDeploy
-    // Basic usage:
-    // createAWTRunLoopMediator. Start client code on another thread. doAWTRunLoop. When client code is finished, stopAWTRunLoop.
-    public static native long createAWTRunLoopMediator();
-    public static native void doAWTRunLoop(long mediator, boolean awtMode, boolean detectDeadlocks);
-    public static native void stopAWTRunLoop(long mediator);
+    static native long createAWTRunLoopMediator();
+    /**
+     * Method to run a nested run-loop. The nested loop is spinned in the javaRunLoop mode, so selectors sent
+     * by [JNFRunLoop performOnMainThreadWaiting] are processed.
+     * @param mediator a native pointer to the mediator object created by createAWTRunLoopMediator
+     * @param processEvents if true - dispatches event while in the nested loop. Used in DnD.
+     *                      Additional attention is needed when using this feature as we short-circuit normal event
+     *                      processing which could break Appkit.
+     *                      (One known example is when the window is resized with the mouse)
+     *
+     *                      if false - all events come after exit form the nested loop
+     */
+    static native void doAWTRunLoop(long mediator, boolean processEvents);
+    static native void stopAWTRunLoop(long mediator);
 
     private native boolean nativeSyncQueue(long timeout);
 
--- a/src/macosx/native/sun/awt/AWTView.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/awt/AWTView.m	Mon Feb 25 10:17:25 2013 +0000
@@ -227,7 +227,7 @@
 
 - (void) mouseMoved: (NSEvent *)event {
     // TODO: better way to redirect move events to the "under" view
-
+    
     NSPoint eventLocation = [event locationInWindow];
     NSPoint localPoint = [self convertPoint: eventLocation fromView: nil];
 
@@ -668,7 +668,7 @@
 
 - (void) setDropTarget:(CDropTarget *)target {
     self._dropTarget = target;
-    [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) onObject:self._dropTarget withObject:nil waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(controlModelControlValid) on:self._dropTarget withObject:nil waitUntilDone:YES];
 }
 
 /********************************  BEGIN NSDraggingSource Interface  ********************************/
@@ -1215,7 +1215,7 @@
     fprintf(stderr, "AWTView InputMethod Selector Called : [abandonInput]\n");
 #endif // IM_DEBUG
 
-    [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) onObject:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(markedTextAbandoned:) on:[NSInputManager currentInputManager] withObject:self waitUntilDone:YES];
     [self unmarkText];
 }
 
--- a/src/macosx/native/sun/awt/ApplicationDelegate.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/awt/ApplicationDelegate.m	Mon Feb 25 10:17:25 2013 +0000
@@ -567,10 +567,9 @@
 {
 JNF_COCOA_ENTER(env);
     [ThreadUtilities performOnMainThread:@selector(_registerForNotification:)
-                                onObject:[ApplicationDelegate class]
+                                      on:[ApplicationDelegate class]
                               withObject:[NSNumber numberWithInt:notificationType]
-                           waitUntilDone:NO
-                                 awtMode:NO]; // AWT_THREADING Safe (non-blocking)
+                           waitUntilDone:NO]; // AWT_THREADING Safe (non-blocking)
 JNF_COCOA_EXIT(env);
 }
 
--- a/src/macosx/native/sun/awt/CClipboard.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/awt/CClipboard.m	Mon Feb 25 10:17:25 2013 +0000
@@ -120,7 +120,7 @@
             fClipboardOwner = JNFNewGlobalRef(inEnv, inClipboard);
         }
     }
-    [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) onObject:self withObject:inTypes waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) on:self withObject:inTypes waitUntilDone:YES];
 }
 
 - (void) _nativeDeclareTypes:(NSArray *)inTypes {
@@ -135,7 +135,7 @@
 - (NSArray *) javaGetTypes {
 
     NSMutableArray *args = [NSMutableArray arrayWithCapacity:1];
-    [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) onObject:self withObject:args waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) on:self withObject:args waitUntilDone:YES];
 
     //NSLog(@"CClipboard getTypes returns %@", [args lastObject]);
     return [args lastObject];
@@ -152,7 +152,7 @@
 - (void) javaSetData:(NSData *)inData forType:(NSString *) inFormat {
 
     CClipboardUpdate *newUpdate = [[CClipboardUpdate alloc] initWithData:inData withFormat:inFormat];
-    [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) onObject:self withObject:newUpdate waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) on:self withObject:newUpdate waitUntilDone:YES];
     [newUpdate release];
 
     //NSLog(@"CClipboard javaSetData forType %@", inFormat);
@@ -170,7 +170,7 @@
 - (NSData *) javaGetDataForType:(NSString *) inFormat {
 
     NSMutableArray *args = [NSMutableArray arrayWithObject:inFormat];
-    [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) onObject:self withObject:args waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) on:self withObject:args waitUntilDone:YES];
 
     //NSLog(@"CClipboard javaGetDataForType %@ returns an NSData", inFormat);
     return [args lastObject];
--- a/src/macosx/native/sun/awt/CDropTarget.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/awt/CDropTarget.m	Mon Feb 25 10:17:25 2013 +0000
@@ -390,8 +390,7 @@
 
     // Release dragging data if any when Java's AWT event thread is all finished.
     // Make sure dragging data is released on the native event thread.
-    [ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) onObject:self
-                              withObject:draggingSequenceNumberID waitUntilDone:NO awtMode:NO];
+    [ThreadUtilities performOnMainThread:@selector(safeReleaseDraggingData:) on:self withObject:draggingSequenceNumberID waitUntilDone:NO];
 }
 
 - (jint)currentJavaActions {
--- a/src/macosx/native/sun/awt/CMenu.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/awt/CMenu.m	Mon Feb 25 10:17:25 2013 +0000
@@ -55,11 +55,11 @@
 //- (void)finalize { [super finalize]; }
 
 - (void)addJavaSubmenu:(CMenu *)submenu {
-    [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) onObject:self withObject:submenu waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:submenu waitUntilDone:YES];
 }
 
 - (void)addJavaMenuItem:(CMenuItem *)theMenuItem {
-    [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) onObject:self withObject:theMenuItem waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:theMenuItem waitUntilDone:YES];
 }
 
 - (void)addNativeItem_OnAppKitThread:(CMenuItem *)itemModified {
@@ -70,7 +70,7 @@
 - (void)setJavaMenuTitle:(NSString *)title {
 
     if (title) {
-        [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) onObject:self withObject:title waitUntilDone:YES awtMode:YES];
+        [ThreadUtilities performOnMainThread:@selector(setNativeMenuTitle_OnAppKitThread:) on:self withObject:title waitUntilDone:YES];
     }
 }
 
@@ -93,7 +93,7 @@
 
 - (void)deleteJavaItem:(jint)index {
 
-    [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) onObject:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(deleteNativeJavaItem_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES];
 }
 
 - (void)deleteNativeJavaItem_OnAppKitThread:(NSNumber *)number {
@@ -139,7 +139,7 @@
     // We use an array here only to be able to get a return value
     NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
 
-    [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) onObject:[CMenu alloc] withObject:args waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES];
 
     aCMenu = (CMenu *)[args objectAtIndex: 0];
 
--- a/src/macosx/native/sun/awt/CMenuBar.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/awt/CMenuBar.m	Mon Feb 25 10:17:25 2013 +0000
@@ -197,7 +197,7 @@
 
     if (self == sActiveMenuBar) {
         NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:-1], nil];
-        [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) onObject:self withObject:args waitUntilDone:YES awtMode:YES];
+        [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES];
         [args release];
     }
 }
@@ -216,7 +216,7 @@
 
     if (self == sActiveMenuBar) {
         NSArray *args = [[NSArray alloc] initWithObjects:theMenu, [NSNumber numberWithInt:index], nil];
-        [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) onObject:self withObject:args waitUntilDone:YES awtMode:YES];
+        [ThreadUtilities performOnMainThread:@selector(nativeAddMenuAtIndex_OnAppKitThread:) on:self withObject:args waitUntilDone:YES];
         [args release];
     }
 }
@@ -286,7 +286,7 @@
 
 - (void) javaDeleteMenu: (jint)index {
     if (self == sActiveMenuBar) {
-        [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) onObject:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES awtMode:YES];
+        [ThreadUtilities performOnMainThread:@selector(nativeDeleteMenu_OnAppKitThread:) on:self withObject:[NSNumber numberWithInt:index] waitUntilDone:YES];
     }
 
     @synchronized(self) {
@@ -388,7 +388,7 @@
     // We use an array here only to be able to get a return value
     NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil];
 
-    [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) onObject:[CMenuBar alloc] withObject:args waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES];
 
     aCMenuBar = (CMenuBar *)[args objectAtIndex: 0];
 
--- a/src/macosx/native/sun/awt/CMenuItem.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/awt/CMenuItem.m	Mon Feb 25 10:17:25 2013 +0000
@@ -386,7 +386,7 @@
         args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO],  nil];
     }
 
-    [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) onObject:[CMenuItem alloc] withObject:args waitUntilDone:YES awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES];
 
     aCMenuItem = (CMenuItem *)[args objectAtIndex: 0];
 
--- a/src/macosx/native/sun/awt/JavaComponentAccessibility.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/awt/JavaComponentAccessibility.m	Mon Feb 25 10:17:25 2013 +0000
@@ -1113,18 +1113,10 @@
     JNIEnv *env = [ThreadUtilities getJNIEnv];
     id value = nil;
 
-    // This code frequently gets called indirectly by Java when VoiceOver is active.
-    // Basically, we just have to know when we going to be a bad state, and do something "special".
-    // Note that while NSApplication isn't technically correct, we post a focus changed notification
-    // (which will call this method, but with the correct codepath) shortly afterwards. See +postFocusChanged.
-    if (sInPerformFromJava) {
-        return [NSApplication sharedApplication];
-    } else {
-        jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop)
-        if (focused != NULL) {
-            if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) {
-                value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView];
-            }
+    jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop)
+    if (focused != NULL) {
+        if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) {
+            value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView];
         }
     }
 
@@ -1149,7 +1141,7 @@
 {
 
 JNF_COCOA_ENTER(env);
-    [ThreadUtilities performOnMainThread:@selector(postFocusChanged:) onObject:[JavaComponentAccessibility class] withObject:nil waitUntilDone:NO awtMode:NO];
+    [ThreadUtilities performOnMainThread:@selector(postFocusChanged:) on:[JavaComponentAccessibility class] withObject:nil waitUntilDone:NO];
 JNF_COCOA_EXIT(env);
 }
 
@@ -1164,7 +1156,7 @@
 (JNIEnv *env, jclass jklass, jlong element)
 {
 JNF_COCOA_ENTER(env);
-    [ThreadUtilities performOnMainThread:@selector(postValueChanged) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO];
+    [ThreadUtilities performOnMainThread:@selector(postValueChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO];
 JNF_COCOA_EXIT(env);
 }
 
@@ -1177,7 +1169,7 @@
 (JNIEnv *env, jclass jklass, jlong element)
 {
 JNF_COCOA_ENTER(env);
-    [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO];
+    [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO];
 JNF_COCOA_EXIT(env);
 }
 
@@ -1191,7 +1183,7 @@
 (JNIEnv *env, jclass jklass, jlong element)
 {
 JNF_COCOA_ENTER(env);
-    [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) onObject:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO awtMode:NO];
+    [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO];
 JNF_COCOA_EXIT(env);
 }
 
--- a/src/macosx/native/sun/awt/LWCToolkit.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/awt/LWCToolkit.m	Mon Feb 25 10:17:25 2013 +0000
@@ -332,7 +332,7 @@
  * Signature: (JZZ)V
  */
 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoop
-(JNIEnv *env, jclass clz, jlong mediator, jboolean awtMode, jboolean detectDeadlocks)
+(JNIEnv *env, jclass clz, jlong mediator, jboolean processEvents)
 {
 AWT_ASSERT_APPKIT_THREAD;
 JNF_COCOA_ENTER(env);
@@ -341,26 +341,25 @@
 
     if (mediatorObject == nil) return;
 
-    if (!sInPerformFromJava || !detectDeadlocks) {
+    // Don't use acceptInputForMode because that doesn't setup autorelease pools properly
+    BOOL isRunning = true;
+    while (![mediatorObject shouldEndRunLoop] && isRunning) {
+        isRunning = [[NSRunLoop currentRunLoop] runMode:[JNFRunLoop javaRunLoopMode]
+                                             beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]];
+        if (processEvents) {
+            //We do not spin a runloop here as date is nil, so does not matter which mode to use
+            NSEvent *event;
+            if ((event = [NSApp nextEventMatchingMask:NSAnyEventMask
+                                           untilDate:nil
+                                              inMode:NSDefaultRunLoopMode
+                                             dequeue:YES]) != nil) {
+                [NSApp sendEvent:event];
+            }
 
-        NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
-        NSDate *distantFuture = [NSDate distantFuture];
-        NSString *mode = (awtMode) ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode;
+        }
+    }
 
-        BOOL isRunning = YES;
-        while (isRunning && ![mediatorObject shouldEndRunLoop]) {
-            // Don't use acceptInputForMode because that doesn't setup autorelease pools properly
-            isRunning = [currentRunLoop runMode:mode beforeDate:distantFuture];
-        }
-
-    }
-#ifndef PRODUCT_BUILD
-    if (sInPerformFromJava) {
-        NSLog(@"Apple AWT: Short-circuiting CToolkit.invokeAndWait trampoline deadlock!!!!!");
-        NSLog(@"\tPlease file a bug report with this message and a reproducible test case.");
-    }
-#endif
-
+   
     CFRelease(mediatorObject);
 
 JNF_COCOA_EXIT(env);
@@ -379,7 +378,7 @@
 
     AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator);
 
-    [ThreadUtilities performOnMainThread:@selector(endRunLoop) onObject:mediatorObject withObject:nil waitUntilDone:NO awtMode:YES];
+    [ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO];
 
     CFRelease(mediatorObject);
 
@@ -463,20 +462,3 @@
 
 }
 
-/*
- * Class:     sun_lwawt_macosx_LWCToolkit
- * Method:    executeNextAppKitEvent
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_sun_lwawt_macosx_LWCToolkit_executeNextAppKitEvent
-(JNIEnv *env, jclass cls)
-{
-    // Simply get the next event in native loop and pass it to execution
-    // We'll be called repeatedly so there's no need to block here
-    NSRunLoop *theRL = [NSRunLoop currentRunLoop];
-    NSApplication * app = [NSApplication sharedApplication];
-    NSEvent * event = [app nextEventMatchingMask: 0xFFFFFFFF untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES];
-    if (event != nil) {
-        [app sendEvent: event];
-    }
-}
--- a/src/macosx/native/sun/osxapp/ThreadUtilities.h	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/osxapp/ThreadUtilities.h	Mon Feb 25 10:17:25 2013 +0000
@@ -122,19 +122,12 @@
 #endif /* AWT_THREAD_ASSERTS */
 // --------------------------------------------------------------------------
 
-// This tracks if we are current inside of a performOnMainThread that is both waiting and in the AWTRunLoopMode
-extern BOOL sInPerformFromJava;
-
-// This is an empty Obj-C object just so that -performSelectorOnMainThread
-// can be used, and to use the Obj-C +initialize feature.
 __attribute__((visibility("default")))
-@interface ThreadUtilities : NSObject { }
+@interface ThreadUtilities { }
 
 + (JNIEnv*)getJNIEnv;
 + (JNIEnv*)getJNIEnvUncached;
 
-+ (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT;
-
 //Wrappers for the corresponding JNFRunLoop methods with a check for main thread
 + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block;
 + (void)performOnMainThread:(SEL)aSelector on:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait;
--- a/src/macosx/native/sun/osxapp/ThreadUtilities.m	Sat Feb 23 19:49:17 2013 -0800
+++ b/src/macosx/native/sun/osxapp/ThreadUtilities.m	Mon Feb 25 10:17:25 2013 +0000
@@ -34,85 +34,6 @@
 JavaVM *jvm = NULL;
 static JNIEnv *appKitEnv = NULL;
 
-static NSArray *sPerformModes = nil;
-static NSArray *sAWTPerformModes = nil;
-
-static BOOL sLoggingEnabled = YES;
-
-#ifdef AWT_THREAD_ASSERTS_ENV_ASSERT
-int sAWTThreadAsserts = 0;
-#endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */
-
-BOOL sInPerformFromJava = NO;
-
-// This class is used so that performSelectorOnMainThread can be
-// controlled a little more easily by us.  It has 2 roles.
-// The first is to set/unset a flag (sInPerformFromJava) that code can
-// check to see if we are in a synchronous perform initiated by a java thread.
-// The second is to implement the CocoaComponent backward compatibility mode.
-@interface CPerformer : NSObject {
-    id fTarget;
-    SEL fSelector;
-    id fArg;
-    BOOL fWait;
-}
-
-- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg wait:(BOOL)wait;
-- (void) perform;
-@end
-
-
-@implementation CPerformer
-
-- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg {
-    return [self initWithTarget:target selector:selector arg:arg wait:YES];
-}
-
-- (id) initWithTarget:(id)target selector:(SEL)selector arg:(id)arg wait:(BOOL)wait {
-    self = [super init];
-    if (self != nil) {
-        fTarget = [target retain];
-        fSelector = selector;
-        fArg = [arg retain];
-        // Only set sInPerformFromJava if this is a synchronous perform
-        fWait = wait;
-    }
-    return self;
-}
-
-- (void) dealloc {
-    [fTarget release];
-    [fArg release];
-    [super dealloc];
-}
-//- (void)finalize { [super finalize]; }
-
-- (void) perform {
-    AWT_ASSERT_APPKIT_THREAD;
-
-    // If this is the first time we're going from java thread -> appkit thread,
-    // set sInPerformFromJava for the duration of the invocation
-    BOOL nestedPerform = sInPerformFromJava;
-    if (fWait) {
-        sInPerformFromJava = YES;
-    }
-
-    // Actually do the work (cheat to avoid a method call)
-    @try {
-        objc_msgSend(fTarget, fSelector, fArg);
-        //[fTarget performSelector:fSelector withObject:fArg];
-    } @catch (NSException *e) {
-        NSLog(@"*** CPerformer: ignoring exception '%@' raised during perform of selector '%@' on target '%@' with args '%@'", e, NSStringFromSelector(fSelector), fTarget, fArg);
-    } @finally {
-        // If we actually set sInPerformFromJava, unset it now
-        if (!nestedPerform && fWait) {
-            sInPerformFromJava = NO;
-        }
-    }
-}
-@end
-
-
 @implementation ThreadUtilities
 
 + (JNIEnv*)getJNIEnv {
@@ -129,36 +50,6 @@
     return env;
 }
 
-+ (void)initialize {
-    // Headless: BOTH
-    // Embedded: BOTH
-    // Multiple Calls: NO
-    // Caller: Obj-C class initialization
-    // Thread: ?
-
-    if (sPerformModes == nil) {
-        // Create list of Run Loop modes to perform on
-        // The default performSelector, with no mode argument, runs in Default,
-        // ModalPanel, and EventTracking modes
-        sPerformModes =    [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, nil];
-        sAWTPerformModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, NSModalPanelRunLoopMode, NSEventTrackingRunLoopMode, [JNFRunLoop javaRunLoopMode], nil];
-
-#ifdef AWT_THREAD_ASSERTS_ENV_ASSERT
-        sAWTThreadAsserts = (getenv("COCOA_AWT_DISABLE_THREAD_ASSERTS") == NULL);
-#endif /* AWT_THREAD_ASSERTS_ENV_ASSERT */
-    }
-}
-
-// These methods can behave slightly differently than the normal
-// performSelector...  In particular, we define a special runloop mode
-// (AWTRunLoopMode) so that we can "block" the main thread against the
-// java event thread without deadlocking. See CToolkit.invokeAndWait.
-+ (void)performOnMainThread:(SEL)aSelector onObject:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait awtMode:(BOOL)inAWT {
-    CPerformer *performer = [[CPerformer alloc] initWithTarget:target selector:aSelector arg:arg wait:wait];
-    [performer performSelectorOnMainThread:@selector(perform) withObject:nil waitUntilDone:wait modes:((inAWT) ? sAWTPerformModes : sPerformModes)]; // AWT_THREADING Safe (cover method)
-    [performer release];
-}
-
 + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block {
     if ([NSThread isMainThread] && wait == YES) {
         block();