8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #import "CDataTransferer.h"
27 #import "ThreadUtilities.h"
28 #import "jni_util.h"
29 #import <Cocoa/Cocoa.h>
30 #import <JavaNativeFoundation/JavaNativeFoundation.h>
31
32 @interface CClipboard : NSObject { }
33 @property NSInteger changeCount;
34 @property jobject clipboardOwner;
35
36 + (CClipboard*)sharedClipboard;
37 - (void)declareTypes:(NSArray *)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env;
38 - (void)checkPasteboard:(id)sender;
39 @end
40
41 @implementation CClipboard
42 @synthesize changeCount = _changeCount;
43 @synthesize clipboardOwner = _clipboardOwner;
44
45 // Clipboard creation is synchronized at the Java level
46 + (CClipboard*)sharedClipboard {
47 static CClipboard* sClipboard = nil;
48 if (sClipboard == nil) {
62 return self;
63 }
64
65 - (void)declareTypes:(NSArray*)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env {
66 @synchronized(self) {
67 if (owner != NULL) {
68 if (self.clipboardOwner != NULL) {
69 JNFDeleteGlobalRef(env, self.clipboardOwner);
70 }
71 self.clipboardOwner = JNFNewGlobalRef(env, owner);
72 }
73 }
74 [ThreadUtilities performOnMainThreadWaiting:YES block:^() {
75 self.changeCount = [[NSPasteboard generalPasteboard] declareTypes:types owner:self];
76 }];
77 }
78
79 - (void)checkPasteboard:(id)sender {
80
81 // This is called via NSApplicationDidBecomeActiveNotification.
82
83 // If the change count on the general pasteboard is different than when we set it
84 // someone else put data on the clipboard. That means the current owner lost ownership.
85
86 NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount];
87
88 if (self.changeCount != newChangeCount) {
89 self.changeCount = newChangeCount;
90
91 // Notify that the content might be changed
92 static JNF_CLASS_CACHE(jc_CClipboard, "sun/lwawt/macosx/CClipboard");
93 static JNF_STATIC_MEMBER_CACHE(jm_contentChanged, jc_CClipboard, "notifyChanged", "()V");
94 JNIEnv *env = [ThreadUtilities getJNIEnv];
95 JNFCallStaticVoidMethod(env, jm_contentChanged);
96
97 // If we have a Java pasteboard owner, tell it that it doesn't own the pasteboard anymore.
98 static JNF_MEMBER_CACHE(jm_lostOwnership, jc_CClipboard, "notifyLostOwnership", "()V");
99 @synchronized(self) {
100 if (self.clipboardOwner) {
101 JNIEnv *env = [ThreadUtilities getJNIEnv];
102 JNFCallVoidMethod(env, self.clipboardOwner, jm_lostOwnership); // AWT_THREADING Safe (event)
103 JNFDeleteGlobalRef(env, self.clipboardOwner);
104 self.clipboardOwner = NULL;
105 }
106 }
107 }
108 }
109
110 - (BOOL) checkPasteboardWithoutNotification:(id)application {
111 AWT_ASSERT_APPKIT_THREAD;
112
113 NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount];
114
115 if (self.changeCount != newChangeCount) {
116 self.changeCount = newChangeCount;
117 return YES;
118 } else {
119 return NO;
120 }
121 }
122
123 @end
124
125 /*
126 * Class: sun_lwawt_macosx_CClipboard
127 * Method: declareTypes
128 * Signature: ([JLsun/awt/datatransfer/SunClipboard;)V
129 */
130 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_declareTypes
131 (JNIEnv *env, jobject inObject, jlongArray inTypes, jobject inJavaClip)
132 {
133 JNF_COCOA_ENTER(env);
134
135 jint i;
136 jint nElements = (*env)->GetArrayLength(env, inTypes);
172 }];
173 JNF_COCOA_EXIT(env);
174 }
175
176 /*
177 * Class: sun_lwawt_macosx_CClipboard
178 * Method: getClipboardFormats
179 * Signature: (J)[J
180 */
181 JNIEXPORT jlongArray JNICALL Java_sun_lwawt_macosx_CClipboard_getClipboardFormats
182 (JNIEnv *env, jobject inObject)
183 {
184 jlongArray returnValue = NULL;
185 JNF_COCOA_ENTER(env);
186
187 __block NSArray* dataTypes;
188 [ThreadUtilities performOnMainThreadWaiting:YES block:^() {
189 dataTypes = [[[NSPasteboard generalPasteboard] types] retain];
190 }];
191 [dataTypes autorelease];
192
193 NSUInteger nFormats = [dataTypes count];
194 NSUInteger knownFormats = 0;
195 NSUInteger i;
196
197 // There can be any number of formats on the general pasteboard. Find out which ones
198 // we know about (i.e., live in the flavormap.properties).
199 for (i = 0; i < nFormats; i++) {
200 NSString *format = (NSString *)[dataTypes objectAtIndex:i];
201 if (indexForFormat(format) != -1)
202 knownFormats++;
203 }
204
205 returnValue = (*env)->NewLongArray(env, knownFormats);
206 if (returnValue == NULL) {
207 return NULL;
208 }
209
210 if (knownFormats == 0) {
211 return returnValue;
212 }
233
234 /*
235 * Class: sun_lwawt_macosx_CClipboard
236 * Method: getClipboardData
237 * Signature: (JJ)[B
238 */
239 JNIEXPORT jbyteArray JNICALL Java_sun_lwawt_macosx_CClipboard_getClipboardData
240 (JNIEnv *env, jobject inObject, jlong format)
241 {
242 jbyteArray returnValue = NULL;
243
244 // Note that this routine makes no attempt to interpret the data, since we're returning
245 // a byte array back to Java. CDataTransferer will do that if necessary.
246 JNF_COCOA_ENTER(env);
247
248 NSString *formatAsString = formatForIndex(format);
249 __block NSData* clipData;
250 [ThreadUtilities performOnMainThreadWaiting:YES block:^() {
251 clipData = [[[NSPasteboard generalPasteboard] dataForType:formatAsString] retain];
252 }];
253
254 if (clipData == NULL) {
255 [JNFException raise:env as:"java/io/IOException" reason:"Font transform has NaN position"];
256 return NULL;
257 } else {
258 [clipData autorelease];
259 }
260
261 NSUInteger dataSize = [clipData length];
262 returnValue = (*env)->NewByteArray(env, dataSize);
263 if (returnValue == NULL) {
264 return NULL;
265 }
266
267 if (dataSize != 0) {
268 const void *dataBuffer = [clipData bytes];
269 (*env)->SetByteArrayRegion(env, returnValue, 0, dataSize, (jbyte *)dataBuffer);
270 }
271
272 JNF_COCOA_EXIT(env);
273 return returnValue;
274 }
275
276 /*
277 * Class: sun_lwawt_macosx_CClipboard
278 * Method: checkPasteboard
279 * Signature: ()V
280 */
281 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CClipboard_checkPasteboardWithoutNotification
282 (JNIEnv *env, jobject inObject)
283 {
284 __block BOOL ret = NO;
285 JNF_COCOA_ENTER(env);
286 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
287 ret = [[CClipboard sharedClipboard] checkPasteboardWithoutNotification:nil];
288 }];
289
290 JNF_COCOA_EXIT(env);
291 return ret;
292 }
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #import "CDataTransferer.h"
27 #import "ThreadUtilities.h"
28 #import "jni_util.h"
29 #import <Cocoa/Cocoa.h>
30 #import <JavaNativeFoundation/JavaNativeFoundation.h>
31
32 @interface CClipboard : NSObject { }
33 @property NSInteger changeCount;
34 @property jobject clipboardOwner;
35
36 + (CClipboard*)sharedClipboard;
37 - (void)declareTypes:(NSArray *)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env;
38 - (void)checkPasteboard:(id)sender;
39 @end
40
41 @implementation CClipboard
42 @synthesize changeCount = _changeCount;
43 @synthesize clipboardOwner = _clipboardOwner;
44
45 // Clipboard creation is synchronized at the Java level
46 + (CClipboard*)sharedClipboard {
47 static CClipboard* sClipboard = nil;
48 if (sClipboard == nil) {
62 return self;
63 }
64
65 - (void)declareTypes:(NSArray*)types withOwner:(jobject)owner jniEnv:(JNIEnv*)env {
66 @synchronized(self) {
67 if (owner != NULL) {
68 if (self.clipboardOwner != NULL) {
69 JNFDeleteGlobalRef(env, self.clipboardOwner);
70 }
71 self.clipboardOwner = JNFNewGlobalRef(env, owner);
72 }
73 }
74 [ThreadUtilities performOnMainThreadWaiting:YES block:^() {
75 self.changeCount = [[NSPasteboard generalPasteboard] declareTypes:types owner:self];
76 }];
77 }
78
79 - (void)checkPasteboard:(id)sender {
80
81 // This is called via NSApplicationDidBecomeActiveNotification.
82
83 // If the change count on the general pasteboard is different than when we set it
84 // someone else put data on the clipboard. That means the current owner lost ownership.
85
86 NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount];
87
88 if (self.changeCount != newChangeCount) {
89 self.changeCount = newChangeCount;
90
91 // Notify that the content might be changed
92 static JNF_CLASS_CACHE(jc_CClipboard, "sun/lwawt/macosx/CClipboard");
93 static JNF_STATIC_MEMBER_CACHE(jm_contentChanged, jc_CClipboard, "notifyChanged", "()V");
94 JNIEnv *env = [ThreadUtilities getJNIEnv];
95 JNFCallStaticVoidMethod(env, jm_contentChanged);
96
97 // If we have a Java pasteboard owner, tell it that it doesn't own the pasteboard anymore.
98 static JNF_MEMBER_CACHE(jm_lostOwnership, jc_CClipboard, "notifyLostOwnership", "()V");
99 @synchronized(self) {
100 if (self.clipboardOwner) {
101 JNIEnv *env = [ThreadUtilities getJNIEnv];
102 JNFCallVoidMethod(env, self.clipboardOwner, jm_lostOwnership); // AWT_THREADING Safe (event)
103 JNFDeleteGlobalRef(env, self.clipboardOwner);
104 self.clipboardOwner = NULL;
105 }
106 }
107 }
108 }
109
110 - (BOOL) checkPasteboardWithoutNotification:(id)application {
111 AWT_ASSERT_APPKIT_THREAD;
112
113 NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount];
114
115 if (self.changeCount != newChangeCount) {
116 self.changeCount = newChangeCount;
117 return YES;
118 } else {
119 return NO;
120 }
121 }
122
123 @end
124
125 /*
126 * Class: sun_lwawt_macosx_CClipboard
127 * Method: declareTypes
128 * Signature: ([JLsun/awt/datatransfer/SunClipboard;)V
129 */
130 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_declareTypes
131 (JNIEnv *env, jobject inObject, jlongArray inTypes, jobject inJavaClip)
132 {
133 JNF_COCOA_ENTER(env);
134
135 jint i;
136 jint nElements = (*env)->GetArrayLength(env, inTypes);
172 }];
173 JNF_COCOA_EXIT(env);
174 }
175
176 /*
177 * Class: sun_lwawt_macosx_CClipboard
178 * Method: getClipboardFormats
179 * Signature: (J)[J
180 */
181 JNIEXPORT jlongArray JNICALL Java_sun_lwawt_macosx_CClipboard_getClipboardFormats
182 (JNIEnv *env, jobject inObject)
183 {
184 jlongArray returnValue = NULL;
185 JNF_COCOA_ENTER(env);
186
187 __block NSArray* dataTypes;
188 [ThreadUtilities performOnMainThreadWaiting:YES block:^() {
189 dataTypes = [[[NSPasteboard generalPasteboard] types] retain];
190 }];
191 [dataTypes autorelease];
192
193 NSUInteger nFormats = [dataTypes count];
194 NSUInteger knownFormats = 0;
195 NSUInteger i;
196
197 // There can be any number of formats on the general pasteboard. Find out which ones
198 // we know about (i.e., live in the flavormap.properties).
199 for (i = 0; i < nFormats; i++) {
200 NSString *format = (NSString *)[dataTypes objectAtIndex:i];
201 if (indexForFormat(format) != -1)
202 knownFormats++;
203 }
204
205 returnValue = (*env)->NewLongArray(env, knownFormats);
206 if (returnValue == NULL) {
207 return NULL;
208 }
209
210 if (knownFormats == 0) {
211 return returnValue;
212 }
233
234 /*
235 * Class: sun_lwawt_macosx_CClipboard
236 * Method: getClipboardData
237 * Signature: (JJ)[B
238 */
239 JNIEXPORT jbyteArray JNICALL Java_sun_lwawt_macosx_CClipboard_getClipboardData
240 (JNIEnv *env, jobject inObject, jlong format)
241 {
242 jbyteArray returnValue = NULL;
243
244 // Note that this routine makes no attempt to interpret the data, since we're returning
245 // a byte array back to Java. CDataTransferer will do that if necessary.
246 JNF_COCOA_ENTER(env);
247
248 NSString *formatAsString = formatForIndex(format);
249 __block NSData* clipData;
250 [ThreadUtilities performOnMainThreadWaiting:YES block:^() {
251 clipData = [[[NSPasteboard generalPasteboard] dataForType:formatAsString] retain];
252 }];
253
254 if (clipData == NULL) {
255 [JNFException raise:env as:"java/io/IOException" reason:"Font transform has NaN position"];
256 return NULL;
257 } else {
258 [clipData autorelease];
259 }
260
261 NSUInteger dataSize = [clipData length];
262 returnValue = (*env)->NewByteArray(env, dataSize);
263 if (returnValue == NULL) {
264 return NULL;
265 }
266
267 if (dataSize != 0) {
268 const void *dataBuffer = [clipData bytes];
269 (*env)->SetByteArrayRegion(env, returnValue, 0, dataSize, (jbyte *)dataBuffer);
270 }
271
272 JNF_COCOA_EXIT(env);
273 return returnValue;
274 }
275
276 /*
277 * Class: sun_lwawt_macosx_CClipboard
278 * Method: checkPasteboard
279 * Signature: ()V
280 */
281 JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CClipboard_checkPasteboardWithoutNotification
282 (JNIEnv *env, jobject inObject)
283 {
284 __block BOOL ret = NO;
285 JNF_COCOA_ENTER(env);
286 [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
287 ret = [[CClipboard sharedClipboard] checkPasteboardWithoutNotification:nil];
288 }];
289
290 JNF_COCOA_EXIT(env);
291 return ret;
292 }
|