Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m
41152 views
/*1* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#import "CDataTransferer.h"26#import "ThreadUtilities.h"27#import "JNIUtilities.h"28#import <Cocoa/Cocoa.h>2930@interface CClipboard : NSObject { }31@property NSInteger changeCount;32@property jobject clipboardOwner;3334+ (CClipboard*)sharedClipboard;35- (void)declareTypes:(NSArray *)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env;36- (void)checkPasteboard:(id)sender;37@end3839@implementation CClipboard40@synthesize changeCount = _changeCount;41@synthesize clipboardOwner = _clipboardOwner;4243// Clipboard creation is synchronized at the Java level44+ (CClipboard*)sharedClipboard {45static CClipboard* sClipboard = nil;46if (sClipboard == nil) {47sClipboard = [[CClipboard alloc] init];48[[NSNotificationCenter defaultCenter] addObserver:sClipboard selector: @selector(checkPasteboard:)49name: NSApplicationDidBecomeActiveNotification50object: nil];51}5253return sClipboard;54}5556- (id)init {57if (self = [super init]) {58self.changeCount = [[NSPasteboard generalPasteboard] changeCount];59}60return self;61}6263- (void)declareTypes:(NSArray*)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env {64@synchronized(self) {65if (owner != NULL) {66if (self.clipboardOwner != NULL) {67(*env)->DeleteGlobalRef(env, self.clipboardOwner);68}69self.clipboardOwner = (*env)->NewGlobalRef(env, owner);70}71}72[ThreadUtilities performOnMainThreadWaiting:YES block:^() {73self.changeCount = [[NSPasteboard generalPasteboard] declareTypes:types owner:self];74}];75}7677- (void)checkPasteboard:(id)sender {7879// This is called via NSApplicationDidBecomeActiveNotification.8081// If the change count on the general pasteboard is different than when we set it82// someone else put data on the clipboard. That means the current owner lost ownership.8384NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount];8586if (self.changeCount != newChangeCount) {87self.changeCount = newChangeCount;8889JNIEnv *env = [ThreadUtilities getJNIEnv];90// Notify that the content might be changed91DECLARE_CLASS(jc_CClipboard, "sun/lwawt/macosx/CClipboard");92DECLARE_STATIC_METHOD(jm_contentChanged, jc_CClipboard, "notifyChanged", "()V");93(*env)->CallStaticVoidMethod(env, jc_CClipboard, jm_contentChanged);94CHECK_EXCEPTION();9596// If we have a Java pasteboard owner, tell it that it doesn't own the pasteboard anymore.97DECLARE_METHOD(jm_lostOwnership, jc_CClipboard, "notifyLostOwnership", "()V");98@synchronized(self) {99if (self.clipboardOwner) {100(*env)->CallVoidMethod(env, self.clipboardOwner, jm_lostOwnership);101CHECK_EXCEPTION();102(*env)->DeleteGlobalRef(env, self.clipboardOwner);103self.clipboardOwner = NULL;104}105}106}107}108109- (BOOL) checkPasteboardWithoutNotification:(id)application {110AWT_ASSERT_APPKIT_THREAD;111112NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount];113114if (self.changeCount != newChangeCount) {115self.changeCount = newChangeCount;116return YES;117} else {118return NO;119}120}121122@end123124/*125* Class: sun_lwawt_macosx_CClipboard126* Method: declareTypes127* Signature: ([JLsun/awt/datatransfer/SunClipboard;)V128*/129JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_declareTypes130(JNIEnv *env, jobject inObject, jlongArray inTypes, jobject inJavaClip)131{132JNI_COCOA_ENTER(env);133134jint i;135jint nElements = (*env)->GetArrayLength(env, inTypes);136NSMutableArray *formatArray = [NSMutableArray arrayWithCapacity:nElements];137jlong *elements = (*env)->GetPrimitiveArrayCritical(env, inTypes, NULL);138139for (i = 0; i < nElements; i++) {140NSString *pbFormat = formatForIndex(elements[i]);141if (pbFormat)142[formatArray addObject:pbFormat];143}144145(*env)->ReleasePrimitiveArrayCritical(env, inTypes, elements, JNI_ABORT);146[[CClipboard sharedClipboard] declareTypes:formatArray withOwner:inJavaClip jniEnv:env];147JNI_COCOA_EXIT(env);148}149150/*151* Class: sun_lwawt_macosx_CClipboard152* Method: setData153* Signature: ([BJ)V154*/155JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_setData156(JNIEnv *env, jobject inObject, jbyteArray inBytes, jlong inFormat)157{158if (inBytes == NULL) {159return;160}161162JNI_COCOA_ENTER(env);163jint nBytes = (*env)->GetArrayLength(env, inBytes);164jbyte *rawBytes = (*env)->GetPrimitiveArrayCritical(env, inBytes, NULL);165CHECK_NULL(rawBytes);166NSData *bytesAsData = [NSData dataWithBytes:rawBytes length:nBytes];167(*env)->ReleasePrimitiveArrayCritical(env, inBytes, rawBytes, JNI_ABORT);168NSString *format = formatForIndex(inFormat);169[ThreadUtilities performOnMainThreadWaiting:YES block:^() {170[[NSPasteboard generalPasteboard] setData:bytesAsData forType:format];171}];172JNI_COCOA_EXIT(env);173}174175/*176* Class: sun_lwawt_macosx_CClipboard177* Method: getClipboardFormats178* Signature: (J)[J179*/180JNIEXPORT jlongArray JNICALL Java_sun_lwawt_macosx_CClipboard_getClipboardFormats181(JNIEnv *env, jobject inObject)182{183jlongArray returnValue = NULL;184JNI_COCOA_ENTER(env);185186__block NSArray* dataTypes;187[ThreadUtilities performOnMainThreadWaiting:YES block:^() {188dataTypes = [[[NSPasteboard generalPasteboard] types] retain];189}];190[dataTypes autorelease];191192NSUInteger nFormats = [dataTypes count];193NSUInteger knownFormats = 0;194NSUInteger i;195196// There can be any number of formats on the general pasteboard. Find out which ones197// we know about (i.e., live in the flavormap.properties).198for (i = 0; i < nFormats; i++) {199NSString *format = (NSString *)[dataTypes objectAtIndex:i];200if (indexForFormat(format) != -1)201knownFormats++;202}203204returnValue = (*env)->NewLongArray(env, knownFormats);205if (returnValue == NULL) {206return NULL;207}208209if (knownFormats == 0) {210return returnValue;211}212213// Now go back and map the formats we found back to Java indexes.214jboolean isCopy;215jlong *lFormats = (*env)->GetLongArrayElements(env, returnValue, &isCopy);216jlong *saveFormats = lFormats;217218for (i = 0; i < nFormats; i++) {219NSString *format = (NSString *)[dataTypes objectAtIndex:i];220jlong index = indexForFormat(format);221222if (index != -1) {223*lFormats = index;224lFormats++;225}226}227228(*env)->ReleaseLongArrayElements(env, returnValue, saveFormats, JNI_COMMIT);229JNI_COCOA_EXIT(env);230return returnValue;231}232233/*234* Class: sun_lwawt_macosx_CClipboard235* Method: getClipboardData236* Signature: (JJ)[B237*/238JNIEXPORT jbyteArray JNICALL Java_sun_lwawt_macosx_CClipboard_getClipboardData239(JNIEnv *env, jobject inObject, jlong format)240{241jbyteArray returnValue = NULL;242243// Note that this routine makes no attempt to interpret the data, since we're returning244// a byte array back to Java. CDataTransferer will do that if necessary.245JNI_COCOA_ENTER(env);246247NSString *formatAsString = formatForIndex(format);248__block NSData* clipData;249[ThreadUtilities performOnMainThreadWaiting:YES block:^() {250clipData = [[[NSPasteboard generalPasteboard] dataForType:formatAsString] retain];251}];252253if (clipData == NULL) {254JNU_ThrowIOException(env, "Font transform has NaN position");255return NULL;256} else {257[clipData autorelease];258}259260NSUInteger dataSize = [clipData length];261returnValue = (*env)->NewByteArray(env, dataSize);262if (returnValue == NULL) {263return NULL;264}265266if (dataSize != 0) {267const void *dataBuffer = [clipData bytes];268(*env)->SetByteArrayRegion(env, returnValue, 0, dataSize, (jbyte *)dataBuffer);269}270271JNI_COCOA_EXIT(env);272return returnValue;273}274275/*276* Class: sun_lwawt_macosx_CClipboard277* Method: checkPasteboard278* Signature: ()V279*/280JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CClipboard_checkPasteboardWithoutNotification281(JNIEnv *env, jobject inObject)282{283__block BOOL ret = NO;284JNI_COCOA_ENTER(env);285[ThreadUtilities performOnMainThreadWaiting:YES block:^(){286ret = [[CClipboard sharedClipboard] checkPasteboardWithoutNotification:nil];287}];288289JNI_COCOA_EXIT(env);290return ret;291}292293294