Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/macosx/native_NOTIOS/sun/awt/CClipboard.m
38829 views
/*1* Copyright (c) 2011, 2016, 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 "CClipboard.h"26#import "CDataTransferer.h"27#import "ThreadUtilities.h"28#import "jni_util.h"29#import <Cocoa/Cocoa.h>30#import <JavaNativeFoundation/JavaNativeFoundation.h>3132static CClipboard *sClipboard = nil;3334//35// CClipboardUpdate is used for mulitple calls to setData that happen before36// the model and AppKit can get back in sync.37//3839@interface CClipboardUpdate : NSObject {40NSData *fData;41NSString *fFormat;42}4344- (id)initWithData:(NSData *)inData withFormat:(NSString *)inFormat;45- (NSData *)data;46- (NSString *)format;4748@end4950@implementation CClipboardUpdate5152- (id)initWithData:(NSData *)inData withFormat:(NSString *)inFormat53{54self = [super init];5556if (self != nil) {57fData = [inData retain];58fFormat = [inFormat retain];59}6061return self;62}6364- (void)dealloc65{66[fData release];67fData = nil;6869[fFormat release];70fFormat = nil;7172[super dealloc];73}7475- (NSData *)data {76return fData;77}7879- (NSString *)format {80return fFormat;81}82@end8384@implementation CClipboard8586// Clipboard creation is synchronized at the Java level.87+ (CClipboard *) sharedClipboard88{89if (sClipboard == nil) {90sClipboard = [[CClipboard alloc] init];91[[NSNotificationCenter defaultCenter] addObserver:sClipboard selector: @selector(checkPasteboard:)92name: NSApplicationDidBecomeActiveNotification93object: nil];94}9596return sClipboard;97}9899- (id) init100{101self = [super init];102103if (self != nil) {104fChangeCount = [[NSPasteboard generalPasteboard] changeCount];105}106107return self;108}109110- (void) javaDeclareTypes:(NSArray *)inTypes withOwner:(jobject)inClipboard jniEnv:(JNIEnv *)inEnv {111112@synchronized(self) {113if (inClipboard != NULL) {114if (fClipboardOwner != NULL) {115JNFDeleteGlobalRef(inEnv, fClipboardOwner);116}117fClipboardOwner = JNFNewGlobalRef(inEnv, inClipboard);118}119}120[ThreadUtilities performOnMainThread:@selector(_nativeDeclareTypes:) on:self withObject:inTypes waitUntilDone:YES];121}122123- (void) _nativeDeclareTypes:(NSArray *)inTypes {124AWT_ASSERT_APPKIT_THREAD;125126fChangeCount = [[NSPasteboard generalPasteboard] declareTypes:inTypes owner:self];127}128129130- (NSArray *) javaGetTypes {131132NSMutableArray *args = [NSMutableArray arrayWithCapacity:1];133[ThreadUtilities performOnMainThread:@selector(_nativeGetTypes:) on:self withObject:args waitUntilDone:YES];134return [args lastObject];135}136137- (void) _nativeGetTypes:(NSMutableArray *)args {138AWT_ASSERT_APPKIT_THREAD;139140[args addObject:[[NSPasteboard generalPasteboard] types]];141}142143- (void) javaSetData:(NSData *)inData forType:(NSString *) inFormat {144145CClipboardUpdate *newUpdate = [[CClipboardUpdate alloc] initWithData:inData withFormat:inFormat];146[ThreadUtilities performOnMainThread:@selector(_nativeSetData:) on:self withObject:newUpdate waitUntilDone:YES];147[newUpdate release];148}149150- (void) _nativeSetData:(CClipboardUpdate *)newUpdate {151AWT_ASSERT_APPKIT_THREAD;152153[[NSPasteboard generalPasteboard] setData:[newUpdate data] forType:[newUpdate format]];154}155156- (NSData *) javaGetDataForType:(NSString *) inFormat {157158NSMutableArray *args = [NSMutableArray arrayWithObject:inFormat];159[ThreadUtilities performOnMainThread:@selector(_nativeGetDataForType:) on:self withObject:args waitUntilDone:YES];160return [args lastObject];161}162163- (void) _nativeGetDataForType:(NSMutableArray *) args {164AWT_ASSERT_APPKIT_THREAD;165166NSData *returnValue = [[NSPasteboard generalPasteboard] dataForType:[args objectAtIndex:0]];167168if (returnValue) [args replaceObjectAtIndex:0 withObject:returnValue];169else [args removeLastObject];170}171172173174- (void) checkPasteboard:(id)application {175AWT_ASSERT_APPKIT_THREAD;176177// This is called via NSApplicationDidBecomeActiveNotification.178179// If the change count on the general pasteboard is different than when we set it180// someone else put data on the clipboard. That means the current owner lost ownership.181NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount];182183if (fChangeCount != newChangeCount) {184fChangeCount = newChangeCount;185186// Notify that the content might be changed187static JNF_CLASS_CACHE(jc_CClipboard, "sun/lwawt/macosx/CClipboard");188static JNF_STATIC_MEMBER_CACHE(jm_contentChanged, jc_CClipboard, "notifyChanged", "()V");189JNIEnv *env = [ThreadUtilities getJNIEnv];190JNFCallStaticVoidMethod(env, jm_contentChanged);191192// If we have a Java pasteboard owner, tell it that it doesn't own the pasteboard anymore.193static JNF_MEMBER_CACHE(jm_lostOwnership, jc_CClipboard, "notifyLostOwnership", "()V");194@synchronized(self) {195if (fClipboardOwner) {196JNIEnv *env = [ThreadUtilities getJNIEnv];197JNFCallVoidMethod(env, fClipboardOwner, jm_lostOwnership); // AWT_THREADING Safe (event)198JNFDeleteGlobalRef(env, fClipboardOwner);199fClipboardOwner = NULL;200}201}202}203}204205- (BOOL) checkPasteboardWithoutNotification:(id)application {206AWT_ASSERT_APPKIT_THREAD;207208NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount];209210if (fChangeCount != newChangeCount) {211fChangeCount = newChangeCount;212return YES;213} else {214return NO;215}216}217218@end219220/*221* Class: sun_lwawt_macosx_CClipboard222* Method: declareTypes223* Signature: ([JLsun/awt/datatransfer/SunClipboard;)V224*/225JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_declareTypes226(JNIEnv *env, jobject inObject, jlongArray inTypes, jobject inJavaClip)227{228JNF_COCOA_ENTER(env);229230jint i;231jint nElements = (*env)->GetArrayLength(env, inTypes);232NSMutableArray *formatArray = [NSMutableArray arrayWithCapacity:nElements];233jlong *elements = (*env)->GetPrimitiveArrayCritical(env, inTypes, NULL);234235for (i = 0; i < nElements; i++) {236NSString *pbFormat = formatForIndex(elements[i]);237if (pbFormat)238[formatArray addObject:pbFormat];239}240241(*env)->ReleasePrimitiveArrayCritical(env, inTypes, elements, JNI_ABORT);242[[CClipboard sharedClipboard] javaDeclareTypes:formatArray withOwner:inJavaClip jniEnv:env];243JNF_COCOA_EXIT(env);244}245246/*247* Class: sun_lwawt_macosx_CClipboard248* Method: setData249* Signature: ([BJ)V250*/251JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_setData252(JNIEnv *env, jobject inObject, jbyteArray inBytes, jlong inFormat)253{254if (inBytes == NULL) {255return;256}257258JNF_COCOA_ENTER(env);259jint nBytes = (*env)->GetArrayLength(env, inBytes);260jbyte *rawBytes = (*env)->GetPrimitiveArrayCritical(env, inBytes, NULL);261CHECK_NULL(rawBytes);262NSData *bytesAsData = [NSData dataWithBytes:rawBytes length:nBytes];263(*env)->ReleasePrimitiveArrayCritical(env, inBytes, rawBytes, JNI_ABORT);264NSString *format = formatForIndex(inFormat);265[[CClipboard sharedClipboard] javaSetData:bytesAsData forType:format];266JNF_COCOA_EXIT(env);267}268269/*270* Class: sun_lwawt_macosx_CClipboard271* Method: getClipboardFormats272* Signature: (J)[J273*/274JNIEXPORT jlongArray JNICALL Java_sun_lwawt_macosx_CClipboard_getClipboardFormats275(JNIEnv *env, jobject inObject)276{277jlongArray returnValue = NULL;278JNF_COCOA_ENTER(env);279280NSArray *dataTypes = [[CClipboard sharedClipboard] javaGetTypes];281NSUInteger nFormats = [dataTypes count];282NSUInteger knownFormats = 0;283NSUInteger i;284285// There can be any number of formats on the general pasteboard. Find out which ones286// we know about (i.e., live in the flavormap.properties).287for (i = 0; i < nFormats; i++) {288NSString *format = (NSString *)[dataTypes objectAtIndex:i];289if (indexForFormat(format) != -1)290knownFormats++;291}292293returnValue = (*env)->NewLongArray(env, knownFormats);294if (returnValue == NULL) {295return NULL;296}297298if (knownFormats == 0) {299return returnValue;300}301302// Now go back and map the formats we found back to Java indexes.303jboolean isCopy;304jlong *lFormats = (*env)->GetLongArrayElements(env, returnValue, &isCopy);305jlong *saveFormats = lFormats;306307for (i = 0; i < nFormats; i++) {308NSString *format = (NSString *)[dataTypes objectAtIndex:i];309jlong index = indexForFormat(format);310311if (index != -1) {312*lFormats = index;313lFormats++;314}315}316317(*env)->ReleaseLongArrayElements(env, returnValue, saveFormats, JNI_COMMIT);318JNF_COCOA_EXIT(env);319return returnValue;320}321322/*323* Class: sun_lwawt_macosx_CClipboard324* Method: getClipboardData325* Signature: (JJ)[B326*/327JNIEXPORT jbyteArray JNICALL Java_sun_lwawt_macosx_CClipboard_getClipboardData328(JNIEnv *env, jobject inObject, jlong format)329{330jbyteArray returnValue = NULL;331332// Note that this routine makes no attempt to interpret the data, since we're returning333// a byte array back to Java. CDataTransferer will do that if necessary.334JNF_COCOA_ENTER(env);335336NSString *formatAsString = formatForIndex(format);337NSData *clipData = [[CClipboard sharedClipboard] javaGetDataForType:formatAsString];338339if (clipData == NULL) {340[JNFException raise:env as:"java/io/IOException" reason:"Font transform has NaN position"];341return NULL;342}343344NSUInteger dataSize = [clipData length];345returnValue = (*env)->NewByteArray(env, dataSize);346if (returnValue == NULL) {347return NULL;348}349350if (dataSize != 0) {351const void *dataBuffer = [clipData bytes];352(*env)->SetByteArrayRegion(env, returnValue, 0, dataSize, (jbyte *)dataBuffer);353}354355JNF_COCOA_EXIT(env);356return returnValue;357}358359/*360* Class: sun_lwawt_macosx_CClipboard361* Method: checkPasteboard362* Signature: ()V363*/364JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CClipboard_checkPasteboardWithoutNotification365(JNIEnv *env, jobject inObject)366{367__block BOOL ret = NO;368JNF_COCOA_ENTER(env);369[ThreadUtilities performOnMainThreadWaiting:YES block:^(){370ret = [[CClipboard sharedClipboard] checkPasteboardWithoutNotification:nil];371}];372373JNF_COCOA_EXIT(env);374return ret;375}376377378379380