7124239: [macosx] sun.awt.SunToolkit.InfiniteLoop exception in realSync called from SwingTestHelper
authorleonidr
Mon, 24 Sep 2012 15:25:17 +0400
changeset 13991 e62879b84a14
parent 13990 3e72145fd93a
child 13992 d1b65c4e924c
7124239: [macosx] sun.awt.SunToolkit.InfiniteLoop exception in realSync called from SwingTestHelper Reviewed-by: anthony
jdk/src/macosx/native/sun/awt/LWCToolkit.m
jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.h
jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m
--- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m	Fri Sep 21 13:48:06 2012 +0400
+++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m	Mon Sep 24 15:25:17 2012 +0400
@@ -33,6 +33,7 @@
 #import "ThreadUtilities.h"
 #import "AWT_debug.h"
 #import "CSystemColors.h"
+#import  "NSApplicationAWT.h"
 
 #import "sun_lwawt_macosx_LWCToolkit.h"
 
@@ -47,7 +48,7 @@
     return eventCount;
 }
 
-+ (void) eventCountPlusPlus{
++ (void) eventCountPlusPlus{    
     eventCount++;
 }
 
@@ -79,7 +80,6 @@
 
 @end
 
-
 /*
  * Class:     sun_lwawt_macosx_LWCToolkit
  * Method:    nativeSyncQueue
@@ -90,12 +90,22 @@
 {
     int currentEventNum = [AWTToolkit getEventCount];
 
-    [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){}];
-
+    NSApplication* sharedApp = [NSApplication sharedApplication];
+    if ([sharedApp isKindOfClass:[NSApplicationAWT class]]) {
+        NSApplicationAWT* theApp = (NSApplicationAWT*)sharedApp;
+        [theApp postDummyEvent];
+        [theApp waitForDummyEvent];
+    } else {
+        // could happen if we are embedded inside SWT application,
+        // in this case just spin a single empty block through 
+        // the event loop to give it a chance to process pending events
+        [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){}];
+    }
+    
     if (([AWTToolkit getEventCount] - currentEventNum) != 0) {
         return JNI_TRUE;
     }
-
+        
     return JNI_FALSE;
 }
 
--- a/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.h	Fri Sep 21 13:48:06 2012 +0400
+++ b/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.h	Mon Sep 24 15:25:17 2012 +0400
@@ -29,11 +29,15 @@
 @interface NSApplicationAWT : NSApplication {
     NSString *fApplicationName;
     NSWindow *eventTransparentWindow;
+    NSTimeInterval dummyEventTimestamp;
+    NSConditionLock* seenDummyEventLock;
 }
 
 - (void) finishLaunching;
 - (void) registerWithProcessManager;
 - (void) setDockIconWithEnv:(JNIEnv *)env;
+- (void) postDummyEvent;
+- (void) waitForDummyEvent;
 
 + (void) runAWTLoopWithApp:(NSApplication*)app;
 
--- a/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m	Fri Sep 21 13:48:06 2012 +0400
+++ b/jdk/src/macosx/native/sun/osxapp/NSApplicationAWT.m	Mon Sep 24 15:25:17 2012 +0400
@@ -52,6 +52,9 @@
 
 AWT_ASSERT_APPKIT_THREAD;
     fApplicationName = nil;
+    dummyEventTimestamp = 0.0;
+    seenDummyEventLock = nil;
+
 
     // NSApplication will call _RegisterApplication with the application's bundle, but there may not be one.
     // So, we need to call it ourselves to ensure the app is set up properly.
@@ -328,6 +331,45 @@
     return event;
 }
 
+// NSTimeInterval has microseconds precision
+#define TS_EQUAL(ts1, ts2) (fabs((ts1) - (ts2)) < 1e-6)
+
+- (void)sendEvent:(NSEvent *)event
+{
+    if ([event type] == NSApplicationDefined && TS_EQUAL([event timestamp], dummyEventTimestamp)) {
+        [seenDummyEventLock lockWhenCondition:NO];
+        [seenDummyEventLock unlockWithCondition:YES];
+    } else {
+        [super sendEvent:event];
+    }
+}
+
+- (void)postDummyEvent {
+    seenDummyEventLock = [[NSConditionLock alloc] initWithCondition:NO];
+    dummyEventTimestamp = [NSProcessInfo processInfo].systemUptime;
+    
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];    
+    NSEvent* event = [NSEvent otherEventWithType: NSApplicationDefined
+                                        location: NSMakePoint(0,0)
+                                   modifierFlags: 0
+                                       timestamp: dummyEventTimestamp
+                                    windowNumber: 0
+                                         context: nil
+                                         subtype: 0
+                                           data1: 0
+                                           data2: 0];
+    [NSApp postEvent: event atStart: NO];
+    [pool drain];
+}
+
+- (void)waitForDummyEvent {
+    [seenDummyEventLock lockWhenCondition:YES];
+    [seenDummyEventLock unlock];
+    [seenDummyEventLock release];
+
+    seenDummyEventLock = nil;
+}
+
 @end