src/macosx/native/sun/awt/CClipboard.m

Print this page

        

*** 21,203 **** * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ - #import "CClipboard.h" #import "CDataTransferer.h" #import "ThreadUtilities.h" #import "jni_util.h" #import <Cocoa/Cocoa.h> #import <JavaNativeFoundation/JavaNativeFoundation.h> ! static CClipboard *sClipboard = nil; ! ! // ! // CClipboardUpdate is used for mulitple calls to setData that happen before ! // the model and AppKit can get back in sync. ! // ! ! @interface CClipboardUpdate : NSObject { ! NSData *fData; ! NSString *fFormat; ! } ! ! - (id)initWithData:(NSData *)inData withFormat:(NSString *)inFormat; ! - (NSData *)data; ! - (NSString *)format; ! ! @end ! ! @implementation CClipboardUpdate ! ! - (id)initWithData:(NSData *)inData withFormat:(NSString *)inFormat ! { ! self = [super init]; ! ! if (self != nil) { ! fData = [inData retain]; ! fFormat = [inFormat retain]; ! } ! ! return self; ! } ! ! - (void)dealloc ! { ! [fData release]; ! fData = nil; ! ! [fFormat release]; ! fFormat = nil; ! ! [super dealloc]; ! } ! ! - (NSData *)data { ! return fData; ! } ! ! - (NSString *)format { ! return fFormat; ! } @end @implementation CClipboard ! // Clipboard creation is synchronized at the Java level. ! + (CClipboard *) sharedClipboard ! { if (sClipboard == nil) { sClipboard = [[CClipboard alloc] init]; [[NSNotificationCenter defaultCenter] addObserver:sClipboard selector: @selector(checkPasteboard:) name: NSApplicationDidBecomeActiveNotification object: nil]; } return sClipboard; } ! - (id) init ! { ! self = [super init]; ! ! if (self != nil) { ! fChangeCount = [[NSPasteboard generalPasteboard] changeCount]; } - return self; } ! - (void) javaDeclareTypes:(NSArray *)inTypes withOwner:(jobject)inClipboard jniEnv:(JNIEnv *)inEnv { ! @synchronized(self) { ! if (inClipboard != NULL) { ! if (fClipboardOwner != NULL) { ! JNFDeleteGlobalRef(inEnv, fClipboardOwner); } ! fClipboardOwner = JNFNewGlobalRef(inEnv, inClipboard); } } ! [ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) on:self withObject:inTypes waitUntilDone:YES]; ! } ! ! - (void) _nativeDeclareTypes:(NSArray *)inTypes { ! AWT_ASSERT_APPKIT_THREAD; ! ! fChangeCount = [[NSPasteboard generalPasteboard] declareTypes:inTypes owner:self]; ! } ! ! ! - (NSArray *) javaGetTypes { ! ! NSMutableArray *args = [NSMutableArray arrayWithCapacity:1]; ! [ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) on:self withObject:args waitUntilDone:YES]; ! return [args lastObject]; ! } ! ! - (void) _nativeGetTypes:(NSMutableArray *)args { ! AWT_ASSERT_APPKIT_THREAD; ! ! [args addObject:[[NSPasteboard generalPasteboard] types]]; ! } ! ! - (void) javaSetData:(NSData *)inData forType:(NSString *) inFormat { ! ! CClipboardUpdate *newUpdate = [[CClipboardUpdate alloc] initWithData:inData withFormat:inFormat]; ! [ThreadUtilities performOnMainThread:@selector(_nativeSetData:) on:self withObject:newUpdate waitUntilDone:YES]; ! [newUpdate release]; ! } ! ! - (void) _nativeSetData:(CClipboardUpdate *)newUpdate { ! AWT_ASSERT_APPKIT_THREAD; ! ! [[NSPasteboard generalPasteboard] setData:[newUpdate data] forType:[newUpdate format]]; ! } ! ! - (NSData *) javaGetDataForType:(NSString *) inFormat { ! ! NSMutableArray *args = [NSMutableArray arrayWithObject:inFormat]; ! [ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) on:self withObject:args waitUntilDone:YES]; ! return [args lastObject]; ! } ! ! - (void) _nativeGetDataForType:(NSMutableArray *) args { ! AWT_ASSERT_APPKIT_THREAD; ! ! NSData *returnValue = [[NSPasteboard generalPasteboard] dataForType:[args objectAtIndex:0]]; ! ! if (returnValue) [args replaceObjectAtIndex:0 withObject:returnValue]; ! else [args removeLastObject]; } ! - (void) checkPasteboard:(id)application { ! AWT_ASSERT_APPKIT_THREAD; - // This is called via NSApplicationDidBecomeActiveNotification. - - // If the change count on the general pasteboard is different than when we set it - // someone else put data on the clipboard. That means the current owner lost ownership. NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount]; ! if (fChangeCount != newChangeCount) { ! fChangeCount = newChangeCount; // Notify that the content might be changed static JNF_CLASS_CACHE(jc_CClipboard, "sun/lwawt/macosx/CClipboard"); static JNF_STATIC_MEMBER_CACHE(jm_contentChanged, jc_CClipboard, "notifyChanged", "()V"); JNIEnv *env = [ThreadUtilities getJNIEnv]; JNFCallStaticVoidMethod(env, jm_contentChanged); // If we have a Java pasteboard owner, tell it that it doesn't own the pasteboard anymore. static JNF_MEMBER_CACHE(jm_lostOwnership, jc_CClipboard, "notifyLostOwnership", "()V"); @synchronized(self) { ! if (fClipboardOwner) { JNIEnv *env = [ThreadUtilities getJNIEnv]; ! JNFCallVoidMethod(env, fClipboardOwner, jm_lostOwnership); // AWT_THREADING Safe (event) ! JNFDeleteGlobalRef(env, fClipboardOwner); ! fClipboardOwner = NULL; } } } } --- 21,104 ---- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #import "CDataTransferer.h" #import "ThreadUtilities.h" #import "jni_util.h" #import <Cocoa/Cocoa.h> #import <JavaNativeFoundation/JavaNativeFoundation.h> ! @interface CClipboard : NSObject { } ! @property NSInteger changeCount; ! @property jobject clipboardOwner; ! ! + (CClipboard*)sharedClipboard; ! - (void)declareTypes:(NSArray *)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env; ! - (void)checkPasteboard:(id)sender; @end @implementation CClipboard + @synthesize changeCount = _changeCount; + @synthesize clipboardOwner = _clipboardOwner; ! // Clipboard creation is synchronized at the Java level ! + (CClipboard*)sharedClipboard { ! static CClipboard* sClipboard = nil; if (sClipboard == nil) { sClipboard = [[CClipboard alloc] init]; [[NSNotificationCenter defaultCenter] addObserver:sClipboard selector: @selector(checkPasteboard:) name: NSApplicationDidBecomeActiveNotification object: nil]; } return sClipboard; } ! - (id)init { ! if (self = [super init]) { ! self.changeCount = [[NSPasteboard generalPasteboard] changeCount]; } return self; } ! - (void)declareTypes:(NSArray*)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env { @synchronized(self) { ! if (owner != NULL) { ! if (self.clipboardOwner != NULL) { ! JNFDeleteGlobalRef(env, self.clipboardOwner); } ! self.clipboardOwner = JNFNewGlobalRef(env, owner); } } ! [ThreadUtilities performOnMainThreadWaiting:YES block:^() { ! self.changeCount = [[NSPasteboard generalPasteboard] declareTypes:types owner:self]; ! }]; } ! - (void)checkPasteboard:(id)sender { NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount]; ! if (self.changeCount != newChangeCount) { ! self.changeCount = newChangeCount; // Notify that the content might be changed static JNF_CLASS_CACHE(jc_CClipboard, "sun/lwawt/macosx/CClipboard"); static JNF_STATIC_MEMBER_CACHE(jm_contentChanged, jc_CClipboard, "notifyChanged", "()V"); JNIEnv *env = [ThreadUtilities getJNIEnv]; JNFCallStaticVoidMethod(env, jm_contentChanged); // If we have a Java pasteboard owner, tell it that it doesn't own the pasteboard anymore. static JNF_MEMBER_CACHE(jm_lostOwnership, jc_CClipboard, "notifyLostOwnership", "()V"); @synchronized(self) { ! if (self.clipboardOwner) { JNIEnv *env = [ThreadUtilities getJNIEnv]; ! JNFCallVoidMethod(env, self.clipboardOwner, jm_lostOwnership); // AWT_THREADING Safe (event) ! JNFDeleteGlobalRef(env, self.clipboardOwner); ! self.clipboardOwner = NULL; } } } }
*** 223,233 **** if (pbFormat) [formatArray addObject:pbFormat]; } (*env)->ReleasePrimitiveArrayCritical(env, inTypes, elements, JNI_ABORT); ! [[CClipboard sharedClipboard] javaDeclareTypes:formatArray withOwner:inJavaClip jniEnv:env]; JNF_COCOA_EXIT(env); } /* * Class: sun_lwawt_macosx_CClipboard --- 124,134 ---- if (pbFormat) [formatArray addObject:pbFormat]; } (*env)->ReleasePrimitiveArrayCritical(env, inTypes, elements, JNI_ABORT); ! [[CClipboard sharedClipboard] declareTypes:formatArray withOwner:inJavaClip jniEnv:env]; JNF_COCOA_EXIT(env); } /* * Class: sun_lwawt_macosx_CClipboard
*** 246,256 **** jbyte *rawBytes = (*env)->GetPrimitiveArrayCritical(env, inBytes, NULL); CHECK_NULL(rawBytes); NSData *bytesAsData = [NSData dataWithBytes:rawBytes length:nBytes]; (*env)->ReleasePrimitiveArrayCritical(env, inBytes, rawBytes, JNI_ABORT); NSString *format = formatForIndex(inFormat); ! [[CClipboard sharedClipboard] javaSetData:bytesAsData forType:format]; JNF_COCOA_EXIT(env); } /* * Class: sun_lwawt_macosx_CClipboard --- 147,159 ---- jbyte *rawBytes = (*env)->GetPrimitiveArrayCritical(env, inBytes, NULL); CHECK_NULL(rawBytes); NSData *bytesAsData = [NSData dataWithBytes:rawBytes length:nBytes]; (*env)->ReleasePrimitiveArrayCritical(env, inBytes, rawBytes, JNI_ABORT); NSString *format = formatForIndex(inFormat); ! [ThreadUtilities performOnMainThreadWaiting:YES block:^() { ! [[NSPasteboard generalPasteboard] setData:bytesAsData forType:format]; ! }]; JNF_COCOA_EXIT(env); } /* * Class: sun_lwawt_macosx_CClipboard
*** 261,271 **** (JNIEnv *env, jobject inObject) { jlongArray returnValue = NULL; JNF_COCOA_ENTER(env); ! NSArray *dataTypes = [[CClipboard sharedClipboard] javaGetTypes]; NSUInteger nFormats = [dataTypes count]; NSUInteger knownFormats = 0; NSUInteger i; // There can be any number of formats on the general pasteboard. Find out which ones --- 164,179 ---- (JNIEnv *env, jobject inObject) { jlongArray returnValue = NULL; JNF_COCOA_ENTER(env); ! __block NSArray* dataTypes; ! [ThreadUtilities performOnMainThreadWaiting:YES block:^() { ! dataTypes = [[[NSPasteboard generalPasteboard] types] retain]; ! }]; ! [dataTypes autorelease]; ! NSUInteger nFormats = [dataTypes count]; NSUInteger knownFormats = 0; NSUInteger i; // There can be any number of formats on the general pasteboard. Find out which ones
*** 318,332 **** // Note that this routine makes no attempt to interpret the data, since we're returning // a byte array back to Java. CDataTransferer will do that if necessary. JNF_COCOA_ENTER(env); NSString *formatAsString = formatForIndex(format); ! NSData *clipData = [[CClipboard sharedClipboard] javaGetDataForType:formatAsString]; if (clipData == NULL) { [JNFException raise:env as:"java/io/IOException" reason:"Font transform has NaN position"]; return NULL; } NSUInteger dataSize = [clipData length]; returnValue = (*env)->NewByteArray(env, dataSize); if (returnValue == NULL) { --- 226,245 ---- // Note that this routine makes no attempt to interpret the data, since we're returning // a byte array back to Java. CDataTransferer will do that if necessary. JNF_COCOA_ENTER(env); NSString *formatAsString = formatForIndex(format); ! __block NSData* clipData; ! [ThreadUtilities performOnMainThreadWaiting:YES block:^() { ! clipData = [[[NSPasteboard generalPasteboard] dataForType:formatAsString] retain]; ! }]; if (clipData == NULL) { [JNFException raise:env as:"java/io/IOException" reason:"Font transform has NaN position"]; return NULL; + } else { + [clipData autorelease]; } NSUInteger dataSize = [clipData length]; returnValue = (*env)->NewByteArray(env, dataSize); if (returnValue == NULL) {
*** 348,362 **** * Signature: ()V */ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_checkPasteboard (JNIEnv *env, jobject inObject ) { ! JNF_COCOA_ENTER(env); [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ [[CClipboard sharedClipboard] checkPasteboard:nil]; }]; ! JNF_COCOA_EXIT(env); } --- 261,275 ---- * Signature: ()V */ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_checkPasteboard (JNIEnv *env, jobject inObject ) { ! JNF_COCOA_ENTER(env); [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ [[CClipboard sharedClipboard] checkPasteboard:nil]; }]; ! JNF_COCOA_EXIT(env); }