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);
}