changeset 5424:b521e3a5b843

7124239: [macosx] sun.awt.SunToolkit.InfiniteLoop exception in realSync called from SwingTestHelper Reviewed-by: anthony, art
author leonidr
date Fri, 22 Jun 2012 14:06:40 +0400
parents d68e2a1744bd
children 8f37aad76b5b
files src/macosx/native/sun/awt/LWCToolkit.m src/macosx/native/sun/osxapp/NSApplicationAWT.h src/macosx/native/sun/osxapp/NSApplicationAWT.m
diffstat 3 files changed, 61 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/macosx/native/sun/awt/LWCToolkit.m	Fri Jun 22 10:20:20 2012 +0100
+++ b/src/macosx/native/sun/awt/LWCToolkit.m	Fri Jun 22 14:06:40 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/src/macosx/native/sun/osxapp/NSApplicationAWT.h	Fri Jun 22 10:20:20 2012 +0100
+++ b/src/macosx/native/sun/osxapp/NSApplicationAWT.h	Fri Jun 22 14:06:40 2012 +0400
@@ -30,11 +30,15 @@
     NSString *fApplicationName;
     BOOL fUseDefaultIcon;
     NSWindow *eventTransparentWindow;
+    NSTimeInterval dummyEventTimestamp;
+    NSConditionLock* seenDummyEventLock;
 }
 
 - (void) finishLaunching;
 - (void) registerWithProcessManager;
 - (void) setDockIconWithEnv:(JNIEnv *)env;
+- (void) postDummyEvent;
+- (void) waitForDummyEvent;
 
 + (void) runAWTLoopWithApp:(NSApplication*)app;
 
--- a/src/macosx/native/sun/osxapp/NSApplicationAWT.m	Fri Jun 22 10:20:20 2012 +0100
+++ b/src/macosx/native/sun/osxapp/NSApplicationAWT.m	Fri Jun 22 14:06:40 2012 +0400
@@ -32,7 +32,6 @@
 #import "ThreadUtilities.h"
 #import "QueuingApplicationDelegate.h"
 
-
 static BOOL sUsingDefaultNIB = YES;
 static NSString *SHARED_FRAMEWORK_BUNDLE = @"/System/Library/Frameworks/JavaVM.framework";
 static id <NSApplicationDelegate> applicationDelegate = nil;
@@ -53,6 +52,8 @@
 AWT_ASSERT_APPKIT_THREAD;
     fApplicationName = nil;
     fUseDefaultIcon = NO;
+    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.
@@ -163,6 +164,7 @@
         char mainClassEnvVar[80];
         snprintf(mainClassEnvVar, sizeof(mainClassEnvVar), "JAVA_MAIN_CLASS_%d", getpid());
         char *mainClass = getenv(mainClassEnvVar);
+
         if (mainClass != NULL) {
             fApplicationName = [NSString stringWithUTF8String:mainClass];
             unsetenv(mainClassEnvVar);
@@ -333,6 +335,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