diff --git a/src/macosx/native/sun/awt/LWCToolkit.m b/src/macosx/native/sun/awt/LWCToolkit.m index 08f0bb7a9d8063fc2256b585410aa091d497f7b3..87e70cd01146ef43e0e2ee708f33d3954adfeafd 100644 --- a/src/macosx/native/sun/awt/LWCToolkit.m +++ b/src/macosx/native/sun/awt/LWCToolkit.m @@ -57,7 +57,7 @@ static long eventCount; return eventCount; } -+ (void) eventCountPlusPlus{ ++ (void) eventCountPlusPlus{ eventCount++; } @@ -131,24 +131,34 @@ static long eventCount; JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_nativeSyncQueue (JNIEnv *env, jobject self, jlong timeout) { - int currentEventNum = [AWTToolkit getEventCount]; + long currentEventNum = [AWTToolkit getEventCount]; NSApplication* sharedApp = [NSApplication sharedApplication]; if ([sharedApp isKindOfClass:[NSApplicationAWT class]]) { NSApplicationAWT* theApp = (NSApplicationAWT*)sharedApp; - [theApp postDummyEvent]; - [theApp waitForDummyEvent:timeout]; + // We use two different API to post events to the application, + // - [NSApplication postEvent] + // - CGEventPost(), see CRobot.m + // It was found that if we post an event via CGEventPost in robot and + // immediately after this we will post the second event via + // [NSApp postEvent] then sometimes the second event will be handled + // first. The opposite isn't proved, but we use both here to be safer. + [theApp postDummyEvent:false]; + [theApp waitForDummyEvent:timeout / 2.0]; + [theApp postDummyEvent:true]; + [theApp waitForDummyEvent:timeout / 2.0]; + } else { // could happen if we are embedded inside SWT application, - // in this case just spin a single empty block through + // 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; } @@ -323,7 +333,7 @@ JNF_COCOA_ENTER(env); 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 - // Processing all events excluding NSApplicationDefined which need to be processed + // Processing all events excluding NSApplicationDefined which need to be processed // on the main loop only (those events are intended for disposing resources) NSEvent *event; if ((event = [NSApp nextEventMatchingMask:(NSAnyEventMask & ~NSApplicationDefinedMask) diff --git a/src/macosx/native/sun/osxapp/NSApplicationAWT.h b/src/macosx/native/sun/osxapp/NSApplicationAWT.h index 1025cd7c5330238eb9e43feb36e78e4ce2e2d52a..69d380032dfed00f382a50f610d4013e4043daeb 100644 --- a/src/macosx/native/sun/osxapp/NSApplicationAWT.h +++ b/src/macosx/native/sun/osxapp/NSApplicationAWT.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,9 +36,9 @@ - (void) finishLaunching; - (void) registerWithProcessManager; - (void) setDockIconWithEnv:(JNIEnv *)env; -- (void) postDummyEvent; +- (void) postDummyEvent:(bool) useCocoa; - (void) postRunnableEvent:(void (^)())block; -- (void) waitForDummyEvent:(long long) timeout; +- (void) waitForDummyEvent:(double) timeout; + (void) runAWTLoopWithApp:(NSApplication*)app; diff --git a/src/macosx/native/sun/osxapp/NSApplicationAWT.m b/src/macosx/native/sun/osxapp/NSApplicationAWT.m index aba26de17cfa1d0de1082c0022ac5c3c1f13e36a..cd4d1d3806d317f67e7a86f10f6a961cf67eef66 100644 --- a/src/macosx/native/sun/osxapp/NSApplicationAWT.m +++ b/src/macosx/native/sun/osxapp/NSApplicationAWT.m @@ -377,9 +377,7 @@ AWT_ASSERT_APPKIT_THREAD; [pool drain]; } - - -- (void)postDummyEvent { +- (void)postDummyEvent:(bool)useCocoa { seenDummyEventLock = [[NSConditionLock alloc] initWithCondition:NO]; dummyEventTimestamp = [NSProcessInfo processInfo].systemUptime; @@ -393,19 +391,28 @@ AWT_ASSERT_APPKIT_THREAD; subtype: 0 data1: 0 data2: 0]; - [NSApp postEvent: event atStart: NO]; + if (useCocoa) { + [NSApp postEvent:event atStart:NO]; + } else { + ProcessSerialNumber psn; + GetCurrentProcess(&psn); + CGEventPostToPSN(&psn, [event CGEvent]); + } [pool drain]; } -- (void)waitForDummyEvent:(long long) timeout { +- (void)waitForDummyEvent:(double)timeout { + bool unlock = true; if (timeout >= 0) { - double sec = ((double) timeout)/1000; - [seenDummyEventLock lockWhenCondition:YES + double sec = timeout / 1000; + unlock = [seenDummyEventLock lockWhenCondition:YES beforeDate:[NSDate dateWithTimeIntervalSinceNow:sec]]; } else { [seenDummyEventLock lockWhenCondition:YES]; } - [seenDummyEventLock unlock]; + if (unlock) { + [seenDummyEventLock unlock]; + } [seenDummyEventLock release]; seenDummyEventLock = nil;