1 |
/* gtkclipboard.c |
/* gtkclipboard.c |
2 |
Copyright (C) 1998, 1999 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
36 |
exception statement from your version. */ |
exception statement from your version. */ |
37 |
|
|
38 |
|
|
39 |
|
#include "jcl.h" |
40 |
#include "gtkpeer.h" |
#include "gtkpeer.h" |
41 |
#include "gnu_java_awt_peer_gtk_GtkClipboard.h" |
#include "gnu_java_awt_peer_gtk_GtkClipboard.h" |
42 |
|
#include "gnu_java_awt_peer_gtk_GtkSelection.h" |
43 |
|
|
44 |
static jmethodID stringSelectionReceivedID; |
#define OBJECT_TARGET 1 |
45 |
static jmethodID stringSelectionHandlerID; |
#define TEXT_TARGET 2 |
46 |
static jmethodID selectionClearID; |
#define IMAGE_TARGET 3 |
47 |
|
#define URI_TARGET 4 |
|
static void selection_received_cb (GtkWidget *, GtkSelectionData *, |
|
|
guint, gpointer); |
|
|
static void selection_get_cb (GtkWidget *, GtkSelectionData *, guint, |
|
|
guint, gpointer); |
|
|
static gint selection_clear_cb (GtkWidget *, GdkEventSelection *); |
|
48 |
|
|
49 |
static GtkWidget *clipboard; |
static GtkClipboard *clipboard; |
|
static jobject cb_obj; |
|
50 |
|
|
51 |
JNIEXPORT void JNICALL |
/* Simple id to keep track of the selection we are currently managing. */ |
52 |
Java_gnu_java_awt_peer_gtk_GtkClipboard_initNativeState (JNIEnv *env, |
static int current_selection = 0; |
53 |
jobject obj) |
|
54 |
|
/* Whether we "own" the clipboard. And may clear it. */ |
55 |
|
static int owner = 0; |
56 |
|
|
57 |
|
static jclass gtk_clipboard_class; |
58 |
|
static jmethodID setSystemContentsID; |
59 |
|
|
60 |
|
static jobject gtk_clipboard_instance = NULL; |
61 |
|
static jmethodID provideContentID; |
62 |
|
static jmethodID provideTextID; |
63 |
|
static jmethodID provideImageID; |
64 |
|
static jmethodID provideURIsID; |
65 |
|
|
66 |
|
static jstring stringTarget; |
67 |
|
static jstring imageTarget; |
68 |
|
static jstring filesTarget; |
69 |
|
|
70 |
|
static void |
71 |
|
cp_gtk_clipboard_owner_change (GtkClipboard *clipboard __attribute__((unused)), |
72 |
|
GdkEvent *event __attribute__((unused)), |
73 |
|
gpointer user_data __attribute__((unused))) |
74 |
{ |
{ |
75 |
|
/* These are only interesting when we are not the owner. Otherwise |
76 |
|
we will have the set and clear functions doing the updating. */ |
77 |
|
JNIEnv *env = cp_gtk_gdk_env (); |
78 |
|
if (!owner) |
79 |
|
(*env)->CallStaticVoidMethod (env, gtk_clipboard_class, |
80 |
|
setSystemContentsID); |
81 |
|
} |
82 |
|
|
83 |
|
JNIEXPORT jboolean JNICALL |
84 |
|
Java_gnu_java_awt_peer_gtk_GtkClipboard_initNativeState (JNIEnv *env, |
85 |
|
jclass gtkclipboard, |
86 |
|
jstring string, |
87 |
|
jstring image, |
88 |
|
jstring files) |
89 |
|
{ |
90 |
|
GdkDisplay* display; |
91 |
|
jboolean can_cache; |
92 |
|
|
93 |
|
gtk_clipboard_class = gtkclipboard; |
94 |
|
setSystemContentsID = (*env)->GetStaticMethodID (env, gtk_clipboard_class, |
95 |
|
"setSystemContents", |
96 |
|
"()V"); |
97 |
|
if (setSystemContentsID == NULL) |
98 |
|
return JNI_FALSE; |
99 |
|
|
100 |
|
stringTarget = (*env)->NewGlobalRef(env, string); |
101 |
|
imageTarget = (*env)->NewGlobalRef(env, image); |
102 |
|
filesTarget = (*env)->NewGlobalRef(env, files); |
103 |
|
|
104 |
gdk_threads_enter (); |
gdk_threads_enter (); |
105 |
|
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); |
106 |
|
|
107 |
if (!stringSelectionReceivedID) |
display = gtk_clipboard_get_display (clipboard); |
108 |
|
if (gdk_display_supports_selection_notification (display)) |
109 |
{ |
{ |
110 |
jclass gtkclipboard; |
g_signal_connect (clipboard, "owner-change", |
111 |
|
G_CALLBACK (cp_gtk_clipboard_owner_change), NULL); |
112 |
gtkclipboard = (*env)->FindClass (env, |
gdk_display_request_selection_notification (display, |
113 |
"gnu/java/awt/peer/gtk/GtkClipboard"); |
GDK_SELECTION_CLIPBOARD); |
114 |
stringSelectionReceivedID = (*env)->GetMethodID (env, gtkclipboard, |
can_cache = JNI_TRUE; |
|
"stringSelectionReceived", |
|
|
"(Ljava/lang/String;)V"); |
|
|
stringSelectionHandlerID = (*env)->GetMethodID (env, gtkclipboard, |
|
|
"stringSelectionHandler", |
|
|
"()Ljava/lang/String;"); |
|
|
selectionClearID = (*env)->GetMethodID (env, gtkclipboard, |
|
|
"selectionClear", "()V"); |
|
115 |
} |
} |
116 |
|
else |
117 |
|
can_cache = JNI_FALSE; |
118 |
|
gdk_threads_leave (); |
119 |
|
|
120 |
cb_obj = (*env)->NewGlobalRef (env, obj); |
return can_cache; |
121 |
|
} |
|
clipboard = gtk_window_new (GTK_WINDOW_TOPLEVEL); |
|
122 |
|
|
123 |
g_signal_connect (G_OBJECT(clipboard), "selection_received", |
static void |
124 |
G_CALLBACK (selection_received_cb), NULL); |
cp_gtk_clipboard_get_func (GtkClipboard *clipboard __attribute__((unused)), |
125 |
|
GtkSelectionData *selection, |
126 |
|
guint info, |
127 |
|
gpointer user_data __attribute__((unused))) |
128 |
|
{ |
129 |
|
JNIEnv *env = cp_gtk_gdk_env (); |
130 |
|
|
131 |
|
if (info == OBJECT_TARGET) |
132 |
|
{ |
133 |
|
const gchar *target_name; |
134 |
|
jstring target_string; |
135 |
|
jbyteArray bytes; |
136 |
|
jint len; |
137 |
|
jbyte *barray; |
138 |
|
|
139 |
|
target_name = gdk_atom_name (selection->target); |
140 |
|
if (target_name == NULL) |
141 |
|
return; |
142 |
|
target_string = (*env)->NewStringUTF (env, target_name); |
143 |
|
if (target_string == NULL) |
144 |
|
return; |
145 |
|
bytes = (*env)->CallObjectMethod(env, |
146 |
|
gtk_clipboard_instance, |
147 |
|
provideContentID, |
148 |
|
target_string); |
149 |
|
if (bytes == NULL) |
150 |
|
return; |
151 |
|
len = (*env)->GetArrayLength(env, bytes); |
152 |
|
if (len <= 0) |
153 |
|
return; |
154 |
|
barray = (*env)->GetByteArrayElements(env, bytes, NULL); |
155 |
|
if (barray == NULL) |
156 |
|
return; |
157 |
|
gtk_selection_data_set (selection, selection->target, 8, |
158 |
|
(guchar *) barray, len); |
159 |
|
|
160 |
g_signal_connect (G_OBJECT(clipboard), "selection_clear_event", |
(*env)->ReleaseByteArrayElements(env, bytes, barray, 0); |
|
G_CALLBACK (selection_clear_cb), NULL); |
|
161 |
|
|
162 |
gtk_selection_add_target (clipboard, GDK_SELECTION_PRIMARY, |
} |
163 |
GDK_TARGET_STRING, 0); |
else if (info == TEXT_TARGET) |
164 |
|
{ |
165 |
|
jstring string; |
166 |
|
const gchar *text; |
167 |
|
int len; |
168 |
|
string = (*env)->CallObjectMethod(env, |
169 |
|
gtk_clipboard_instance, |
170 |
|
provideTextID); |
171 |
|
if (string == NULL) |
172 |
|
return; |
173 |
|
len = (*env)->GetStringUTFLength (env, string); |
174 |
|
if (len == -1) |
175 |
|
return; |
176 |
|
text = (*env)->GetStringUTFChars (env, string, NULL); |
177 |
|
if (text == NULL) |
178 |
|
return; |
179 |
|
|
180 |
g_signal_connect (G_OBJECT(clipboard), "selection_get", |
gtk_selection_data_set_text (selection, text, len); |
181 |
G_CALLBACK (selection_get_cb), NULL); |
(*env)->ReleaseStringUTFChars (env, string, text); |
182 |
|
} |
183 |
|
else if (info == IMAGE_TARGET) |
184 |
|
{ |
185 |
|
jobject gtkimage; |
186 |
|
GdkPixbuf *pixbuf = NULL; |
187 |
|
|
188 |
|
gtkimage = (*env)->CallObjectMethod(env, |
189 |
|
gtk_clipboard_instance, |
190 |
|
provideImageID); |
191 |
|
if (gtkimage == NULL) |
192 |
|
return; |
193 |
|
|
194 |
|
pixbuf = cp_gtk_image_get_pixbuf (env, gtkimage); |
195 |
|
if (pixbuf != NULL) |
196 |
|
{ |
197 |
|
gtk_selection_data_set_pixbuf (selection, pixbuf); |
198 |
|
|
199 |
|
/* if the GtkImage is offscreen, this is a temporary pixbuf |
200 |
|
which should be thrown out. */ |
201 |
|
if(cp_gtk_image_is_offscreen (env, gtkimage) == JNI_TRUE) |
202 |
|
gdk_pixbuf_unref (pixbuf); |
203 |
|
} |
204 |
|
} |
205 |
|
else if (info == URI_TARGET) |
206 |
|
{ |
207 |
|
jobjectArray uris; |
208 |
|
jint count; |
209 |
|
int i; |
210 |
|
gchar **list; |
211 |
|
|
212 |
|
uris = (*env)->CallObjectMethod(env, |
213 |
|
gtk_clipboard_instance, |
214 |
|
provideURIsID); |
215 |
|
if (uris == NULL) |
216 |
|
return; |
217 |
|
count = (*env)->GetArrayLength (env, uris); |
218 |
|
if (count <= 0) |
219 |
|
return; |
220 |
|
|
221 |
|
list = (gchar **) JCL_malloc (env, (count + 1) * sizeof (gchar *)); |
222 |
|
for (i = 0; i < count; i++) |
223 |
|
{ |
224 |
|
const char *text; |
225 |
|
jstring uri; |
226 |
|
|
227 |
|
/* Mark NULL in so case of some error we can find the end. */ |
228 |
|
list[i] = NULL; |
229 |
|
uri = (*env)->GetObjectArrayElement (env, uris, i); |
230 |
|
if (uri == NULL) |
231 |
|
break; |
232 |
|
text = (*env)->GetStringUTFChars (env, uri, NULL); |
233 |
|
if (text == NULL) |
234 |
|
break; |
235 |
|
list[i] = strdup (text); |
236 |
|
(*env)->ReleaseStringUTFChars (env, uri, text); |
237 |
|
} |
238 |
|
|
239 |
|
if (i == count) |
240 |
|
{ |
241 |
|
list[count] = NULL; |
242 |
|
gtk_selection_data_set_uris (selection, list); |
243 |
|
} |
244 |
|
|
245 |
|
for (i = 0; list[i] != NULL; i++) |
246 |
|
free (list[i]); |
247 |
|
JCL_free (env, list); |
248 |
|
} |
249 |
|
} |
250 |
|
|
251 |
gdk_threads_leave (); |
static void |
252 |
|
cp_gtk_clipboard_clear_func (GtkClipboard *clipboard __attribute__((unused)), |
253 |
|
gpointer user_data) |
254 |
|
{ |
255 |
|
if (owner && (int) user_data == current_selection) |
256 |
|
{ |
257 |
|
JNIEnv *env = cp_gtk_gdk_env(); |
258 |
|
owner = 0; |
259 |
|
(*env)->CallStaticVoidMethod (env, gtk_clipboard_class, |
260 |
|
setSystemContentsID); |
261 |
|
} |
262 |
} |
} |
263 |
|
|
264 |
JNIEXPORT void JNICALL |
JNIEXPORT void JNICALL |
265 |
Java_gnu_java_awt_peer_gtk_GtkClipboard_requestStringConversion |
Java_gnu_java_awt_peer_gtk_GtkClipboard_advertiseContent |
266 |
(JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused))) |
(JNIEnv *env, |
267 |
|
jobject instance, |
268 |
|
jobjectArray mime_array, |
269 |
|
jboolean add_text, |
270 |
|
jboolean add_images __attribute__((unused)), |
271 |
|
jboolean add_uris __attribute__((unused))) |
272 |
{ |
{ |
273 |
|
GtkTargetList *target_list; |
274 |
|
GList *list; |
275 |
|
GtkTargetEntry *targets; |
276 |
|
gint n, i; |
277 |
|
|
278 |
gdk_threads_enter (); |
gdk_threads_enter (); |
279 |
|
target_list = gtk_target_list_new (NULL, 0); |
280 |
|
|
281 |
|
if (mime_array != NULL) |
282 |
|
{ |
283 |
|
n = (*env)->GetArrayLength (env, mime_array); |
284 |
|
for (i = 0; i < n; i++) |
285 |
|
{ |
286 |
|
const char *text; |
287 |
|
jstring target; |
288 |
|
GdkAtom atom; |
289 |
|
|
290 |
|
target = (*env)->GetObjectArrayElement (env, mime_array, i); |
291 |
|
if (target == NULL) |
292 |
|
break; |
293 |
|
text = (*env)->GetStringUTFChars (env, target, NULL); |
294 |
|
if (text == NULL) |
295 |
|
break; |
296 |
|
|
297 |
gtk_selection_convert (clipboard, GDK_SELECTION_PRIMARY, |
atom = gdk_atom_intern (text, FALSE); |
298 |
GDK_TARGET_STRING, GDK_CURRENT_TIME); |
gtk_target_list_add (target_list, atom, 0, OBJECT_TARGET); |
299 |
|
|
300 |
|
(*env)->ReleaseStringUTFChars (env, target, text); |
301 |
|
} |
302 |
|
} |
303 |
|
|
304 |
|
/* Add extra targets that gtk+ can provide/translate for us. */ |
305 |
|
if (add_text) |
306 |
|
gtk_target_list_add_text_targets (target_list, TEXT_TARGET); |
307 |
|
if (add_images) |
308 |
|
gtk_target_list_add_image_targets (target_list, IMAGE_TARGET, TRUE); |
309 |
|
if (add_uris) |
310 |
|
gtk_target_list_add_uri_targets (target_list, URI_TARGET); |
311 |
|
|
312 |
|
/* Turn list into a target table. */ |
313 |
|
n = g_list_length (target_list->list); |
314 |
|
if (n > 0) |
315 |
|
{ |
316 |
|
targets = g_new (GtkTargetEntry, n); |
317 |
|
for (list = target_list->list, i = 0; |
318 |
|
list != NULL; |
319 |
|
list = list->next, i++) |
320 |
|
{ |
321 |
|
GtkTargetPair *pair = (GtkTargetPair *) list->data; |
322 |
|
targets[i].target = gdk_atom_name (pair->target); |
323 |
|
targets[i].flags = pair->flags; |
324 |
|
targets[i].info = pair->info; |
325 |
|
} |
326 |
|
|
327 |
|
/* Set the targets plus callback functions and ask for the clipboard |
328 |
|
to be stored when the application exists. */ |
329 |
|
current_selection++; |
330 |
|
if (gtk_clipboard_set_with_data (clipboard, targets, n, |
331 |
|
cp_gtk_clipboard_get_func, |
332 |
|
cp_gtk_clipboard_clear_func, |
333 |
|
(gpointer) current_selection)) |
334 |
|
{ |
335 |
|
owner = 1; |
336 |
|
if (gtk_clipboard_instance == NULL) |
337 |
|
{ |
338 |
|
JNIEnv *env = cp_gtk_gdk_env (); |
339 |
|
gtk_clipboard_instance = (*env)->NewGlobalRef(env, instance); |
340 |
|
|
341 |
|
provideContentID |
342 |
|
= (*env)->GetMethodID (env, gtk_clipboard_class, |
343 |
|
"provideContent", |
344 |
|
"(Ljava/lang/String;)[B"); |
345 |
|
if (provideContentID == NULL) |
346 |
|
return; |
347 |
|
|
348 |
|
provideTextID |
349 |
|
= (*env)->GetMethodID (env, gtk_clipboard_class, |
350 |
|
"provideText", "()Ljava/lang/String;"); |
351 |
|
if (provideTextID == NULL) |
352 |
|
return; |
353 |
|
|
354 |
|
provideImageID |
355 |
|
= (*env)->GetMethodID (env, gtk_clipboard_class, |
356 |
|
"provideImage", |
357 |
|
"()Lgnu/java/awt/peer/gtk/GtkImage;"); |
358 |
|
if (provideImageID == NULL) |
359 |
|
return; |
360 |
|
|
361 |
|
provideURIsID |
362 |
|
= (*env)->GetMethodID (env, gtk_clipboard_class, |
363 |
|
"provideURIs", |
364 |
|
"()[Ljava/lang/String;"); |
365 |
|
if (provideURIsID == NULL) |
366 |
|
return; |
367 |
|
} |
368 |
|
gtk_clipboard_set_can_store (clipboard, NULL, 0); |
369 |
|
} |
370 |
|
else |
371 |
|
{ |
372 |
|
owner = 0; |
373 |
|
(*env)->CallStaticVoidMethod (env, gtk_clipboard_class, |
374 |
|
setSystemContentsID); |
375 |
|
} |
376 |
|
|
377 |
|
for (i = 0; i < n; i++) |
378 |
|
g_free (targets[i].target); |
379 |
|
g_free (targets); |
380 |
|
} |
381 |
|
else if (owner) |
382 |
|
{ |
383 |
|
gtk_clipboard_clear (clipboard); |
384 |
|
owner = 0; |
385 |
|
} |
386 |
|
|
387 |
|
gtk_target_list_unref (target_list); |
388 |
gdk_threads_leave (); |
gdk_threads_leave (); |
389 |
} |
} |
390 |
|
|
391 |
|
|
392 |
|
/* GtkSelection native methods. Put here for convenience since they |
393 |
|
need access to the current clipboard. */ |
394 |
|
|
395 |
|
static jmethodID mimeTypesAvailableID; |
396 |
|
|
397 |
|
/* Note this is actually just a GtkClipboardReceivedFunc, not a real |
398 |
|
GtkClipboardTargetsReceivedFunc, see requestMimeTypes. */ |
399 |
static void |
static void |
400 |
selection_received_cb (GtkWidget *widget __attribute__((unused)), |
cp_gtk_clipboard_targets_received (GtkClipboard *clipboard |
401 |
GtkSelectionData *selection_data __attribute__((unused)), |
__attribute__((unused)), |
402 |
guint time __attribute__((unused)), |
GtkSelectionData *target_data, |
403 |
gpointer data __attribute__((unused))) |
gpointer selection) |
404 |
{ |
{ |
405 |
/* Check to see if retrieval succeeded */ |
GdkAtom *targets = NULL; |
406 |
if (selection_data->length < 0 |
gint targets_len = 0; |
407 |
|| selection_data->type != GDK_SELECTION_TYPE_STRING) |
gchar **target_strings = NULL; |
408 |
|
jobjectArray strings = NULL; |
409 |
|
int strings_len = 0; |
410 |
|
gboolean include_text = FALSE; |
411 |
|
gboolean include_image = FALSE; |
412 |
|
gboolean include_uris = FALSE; |
413 |
|
jobject selection_obj = (jobject) selection; |
414 |
|
JNIEnv *env = cp_gtk_gdk_env (); |
415 |
|
|
416 |
|
if (target_data != NULL && target_data->length > 0) |
417 |
{ |
{ |
418 |
gdk_threads_leave (); |
include_text = gtk_selection_data_targets_include_text (target_data); |
419 |
|
include_image = gtk_selection_data_targets_include_image (target_data, |
420 |
|
TRUE); |
421 |
|
if (gtk_selection_data_get_targets (target_data, &targets, &targets_len)) |
422 |
|
{ |
423 |
|
int i; |
424 |
|
GdkAtom uri_list_atom = gdk_atom_intern ("text/uri-list", FALSE); |
425 |
|
target_strings = g_new (gchar*, targets_len); |
426 |
|
if (target_strings != NULL) |
427 |
|
for (i = 0; i < targets_len; i++) |
428 |
|
{ |
429 |
|
gchar *name = gdk_atom_name (targets[i]); |
430 |
|
if (strchr (name, '/') != NULL) |
431 |
|
{ |
432 |
|
target_strings[i] = name; |
433 |
|
strings_len++; |
434 |
|
if (! include_uris && targets[i] == uri_list_atom) |
435 |
|
include_uris = TRUE; |
436 |
|
} |
437 |
|
else |
438 |
|
target_strings[i] = NULL; |
439 |
|
} |
440 |
|
} |
441 |
|
|
442 |
|
if (target_strings != NULL) |
443 |
|
{ |
444 |
|
int i = 0, j = 0; |
445 |
|
jclass stringClass; |
446 |
|
|
447 |
|
if (include_text) |
448 |
|
strings_len++; |
449 |
|
if (include_image) |
450 |
|
strings_len++; |
451 |
|
if (include_uris) |
452 |
|
strings_len++; |
453 |
|
|
454 |
|
stringClass = (*env)->FindClass (env, "java/lang/String"); |
455 |
|
strings = (*env)->NewObjectArray (env, strings_len, stringClass, |
456 |
|
NULL); |
457 |
|
if (strings != NULL) |
458 |
|
{ |
459 |
|
if (include_text) |
460 |
|
(*env)->SetObjectArrayElement (env, strings, i++, |
461 |
|
stringTarget); |
462 |
|
if (include_image) |
463 |
|
(*env)->SetObjectArrayElement (env, strings, i++, |
464 |
|
imageTarget); |
465 |
|
if (include_uris) |
466 |
|
(*env)->SetObjectArrayElement (env, strings, i++, |
467 |
|
filesTarget); |
468 |
|
|
469 |
|
while(i < strings_len) |
470 |
|
{ |
471 |
|
if (target_strings[j] == NULL) |
472 |
|
j++; |
473 |
|
else |
474 |
|
{ |
475 |
|
jstring string; |
476 |
|
string = (*env)->NewStringUTF (env, |
477 |
|
target_strings[j++]); |
478 |
|
if (string == NULL) |
479 |
|
break; |
480 |
|
(*env)->SetObjectArrayElement (env, strings, i++, |
481 |
|
string); |
482 |
|
} |
483 |
|
} |
484 |
|
} |
485 |
|
|
486 |
|
for (i = 0; i < targets_len; i++) |
487 |
|
g_free (target_strings[i]); |
488 |
|
g_free (target_strings); |
489 |
|
} |
490 |
|
} |
491 |
|
|
492 |
|
(*env)->CallVoidMethod (env, selection_obj, |
493 |
|
mimeTypesAvailableID, |
494 |
|
strings); |
495 |
|
(*env)->DeleteGlobalRef (env, selection_obj); |
496 |
|
} |
497 |
|
|
498 |
(*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), cb_obj, stringSelectionReceivedID, |
JNIEXPORT void JNICALL |
499 |
NULL); |
Java_gnu_java_awt_peer_gtk_GtkSelection_requestMimeTypes |
500 |
|
(JNIEnv *env, jobject selection) |
501 |
|
{ |
502 |
|
jobject selection_obj; |
503 |
|
selection_obj = (*env)->NewGlobalRef(env, selection); |
504 |
|
if (selection_obj == NULL) |
505 |
|
return; |
506 |
|
|
507 |
gdk_threads_enter (); |
if (mimeTypesAvailableID == NULL) |
508 |
|
{ |
509 |
|
jclass gtk_selection_class; |
510 |
|
gtk_selection_class = (*env)->GetObjectClass (env, selection_obj); |
511 |
|
mimeTypesAvailableID = (*env)->GetMethodID (env, gtk_selection_class, |
512 |
|
"mimeTypesAvailable", |
513 |
|
"([Ljava/lang/String;)V"); |
514 |
|
if (mimeTypesAvailableID == NULL) |
515 |
|
return; |
516 |
} |
} |
517 |
|
|
518 |
|
/* We would have liked to call gtk_clipboard_request_targets () |
519 |
|
since that is more general. But the result of that, an array of |
520 |
|
GdkAtoms, cannot be used with the |
521 |
|
gtk_selection_data_targets_include_<x> functions (despite what |
522 |
|
the name suggests). */ |
523 |
|
gdk_threads_enter (); |
524 |
|
gtk_clipboard_request_contents (clipboard, |
525 |
|
gdk_atom_intern ("TARGETS", FALSE), |
526 |
|
cp_gtk_clipboard_targets_received, |
527 |
|
(gpointer) selection_obj); |
528 |
|
gdk_threads_leave (); |
529 |
|
} |
530 |
|
|
531 |
|
|
532 |
|
static jmethodID textAvailableID; |
533 |
|
|
534 |
|
static void |
535 |
|
cp_gtk_clipboard_text_received (GtkClipboard *clipboard |
536 |
|
__attribute__((unused)), |
537 |
|
const gchar *text, |
538 |
|
gpointer selection) |
539 |
|
{ |
540 |
|
jstring string; |
541 |
|
jobject selection_obj = (jobject) selection; |
542 |
|
|
543 |
|
JNIEnv *env = cp_gtk_gdk_env (); |
544 |
|
if (text != NULL) |
545 |
|
string = (*env)->NewStringUTF (env, text); |
546 |
else |
else |
547 |
{ |
string = NULL; |
|
char *str = (char *) selection_data->data; |
|
|
|
|
|
gdk_threads_leave (); |
|
548 |
|
|
549 |
(*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), cb_obj, stringSelectionReceivedID, |
(*env)->CallVoidMethod (env, selection_obj, |
550 |
(*cp_gtk_gdk_env())->NewStringUTF (cp_gtk_gdk_env(), str)); |
textAvailableID, |
551 |
|
string); |
552 |
|
(*env)->DeleteGlobalRef (env, selection_obj); |
553 |
|
} |
554 |
|
|
555 |
gdk_threads_enter (); |
JNIEXPORT void JNICALL |
556 |
|
Java_gnu_java_awt_peer_gtk_GtkSelection_requestText |
557 |
|
(JNIEnv *env, jobject selection) |
558 |
|
{ |
559 |
|
jobject selection_obj; |
560 |
|
selection_obj = (*env)->NewGlobalRef(env, selection); |
561 |
|
if (selection_obj == NULL) |
562 |
|
return; |
563 |
|
|
564 |
|
if (textAvailableID == NULL) |
565 |
|
{ |
566 |
|
jclass gtk_selection_class; |
567 |
|
gtk_selection_class = (*env)->GetObjectClass (env, selection_obj); |
568 |
|
textAvailableID = (*env)->GetMethodID (env, gtk_selection_class, |
569 |
|
"textAvailable", |
570 |
|
"(Ljava/lang/String;)V"); |
571 |
|
if (textAvailableID == NULL) |
572 |
|
return; |
573 |
} |
} |
574 |
|
|
575 |
return; |
gdk_threads_enter (); |
576 |
|
gtk_clipboard_request_text (clipboard, |
577 |
|
cp_gtk_clipboard_text_received, |
578 |
|
(gpointer) selection_obj); |
579 |
|
gdk_threads_leave (); |
580 |
} |
} |
581 |
|
|
582 |
|
static jmethodID imageAvailableID; |
583 |
|
|
584 |
static void |
static void |
585 |
selection_get_cb (GtkWidget *widget __attribute__((unused)), |
cp_gtk_clipboard_image_received (GtkClipboard *clipboard |
586 |
GtkSelectionData *selection_data, |
__attribute__((unused)), |
587 |
guint info __attribute__((unused)), |
GdkPixbuf *pixbuf, |
588 |
guint time __attribute__((unused)), |
gpointer selection) |
|
gpointer data __attribute__((unused))) |
|
589 |
{ |
{ |
590 |
jstring jstr; |
jobject pointer = NULL; |
591 |
const char *utf; |
jobject selection_obj = (jobject) selection; |
592 |
jsize utflen; |
JNIEnv *env = cp_gtk_gdk_env (); |
593 |
|
|
594 |
gdk_threads_leave (); |
if (pixbuf != NULL) |
595 |
|
{ |
596 |
|
g_object_ref (pixbuf); |
597 |
|
pointer = JCL_NewRawDataObject (env, (void *) pixbuf); |
598 |
|
} |
599 |
|
|
600 |
jstr = (*cp_gtk_gdk_env())->CallObjectMethod (cp_gtk_gdk_env(), cb_obj, |
(*env)->CallVoidMethod (env, selection_obj, |
601 |
stringSelectionHandlerID); |
imageAvailableID, |
602 |
|
pointer); |
603 |
|
(*env)->DeleteGlobalRef (env, selection_obj); |
604 |
|
} |
605 |
|
|
606 |
gdk_threads_enter (); |
JNIEXPORT void JNICALL |
607 |
|
Java_gnu_java_awt_peer_gtk_GtkSelection_requestImage (JNIEnv *env, jobject obj) |
608 |
|
{ |
609 |
|
jobject selection_obj; |
610 |
|
selection_obj = (*env)->NewGlobalRef(env, obj); |
611 |
|
if (selection_obj == NULL) |
612 |
|
return; |
613 |
|
|
614 |
if (!jstr) |
if (imageAvailableID == NULL) |
615 |
{ |
{ |
616 |
gtk_selection_data_set (selection_data, |
jclass gtk_selection_class; |
617 |
GDK_TARGET_STRING, 8, NULL, 0); |
gtk_selection_class = (*env)->GetObjectClass (env, selection_obj); |
618 |
return; |
imageAvailableID = (*env)->GetMethodID (env, gtk_selection_class, |
619 |
|
"imageAvailable", |
620 |
|
"(Lgnu/classpath/Pointer;)V"); |
621 |
|
if (imageAvailableID == NULL) |
622 |
|
return; |
623 |
} |
} |
624 |
|
|
625 |
utflen = (*cp_gtk_gdk_env())->GetStringUTFLength (cp_gtk_gdk_env(), jstr); |
gdk_threads_enter (); |
626 |
utf = (*cp_gtk_gdk_env())->GetStringUTFChars (cp_gtk_gdk_env(), jstr, NULL); |
gtk_clipboard_request_image (clipboard, |
627 |
|
cp_gtk_clipboard_image_received, |
628 |
|
(gpointer) selection_obj); |
629 |
|
gdk_threads_leave (); |
630 |
|
} |
631 |
|
|
632 |
gtk_selection_data_set (selection_data, GDK_TARGET_STRING, 8, |
static jmethodID urisAvailableID; |
633 |
(const unsigned char*)utf, utflen); |
|
634 |
|
static void |
635 |
|
cp_gtk_clipboard_uris_received (GtkClipboard *clipboard |
636 |
|
__attribute__((unused)), |
637 |
|
GtkSelectionData *uri_data, |
638 |
|
gpointer selection) |
639 |
|
{ |
640 |
|
gchar **uris = NULL; |
641 |
|
jobjectArray strings = NULL; |
642 |
|
jobject selection_obj = (jobject) selection; |
643 |
|
JNIEnv *env = cp_gtk_gdk_env (); |
644 |
|
|
645 |
|
if (uri_data != NULL) |
646 |
|
uris = gtk_selection_data_get_uris (uri_data); |
647 |
|
|
648 |
|
if (uris != NULL) |
649 |
|
{ |
650 |
|
int len, i; |
651 |
|
gchar **count = uris; |
652 |
|
jclass stringClass = (*env)->FindClass (env, "java/lang/String"); |
653 |
|
|
654 |
|
len = 0; |
655 |
|
while (count[len]) |
656 |
|
len++; |
657 |
|
|
658 |
|
strings = (*env)->NewObjectArray (env, len, stringClass, NULL); |
659 |
|
if (strings != NULL) |
660 |
|
{ |
661 |
|
for (i = 0; i < len; i++) |
662 |
|
{ |
663 |
|
jstring string = (*env)->NewStringUTF (env, uris[i]); |
664 |
|
if (string == NULL) |
665 |
|
break; |
666 |
|
(*env)->SetObjectArrayElement (env, strings, i, string); |
667 |
|
} |
668 |
|
} |
669 |
|
g_strfreev (uris); |
670 |
|
} |
671 |
|
|
672 |
(*cp_gtk_gdk_env())->ReleaseStringUTFChars (cp_gtk_gdk_env(), jstr, utf); |
(*env)->CallVoidMethod (env, selection_obj, |
673 |
|
urisAvailableID, |
674 |
|
strings); |
675 |
|
(*env)->DeleteGlobalRef (env, selection_obj); |
676 |
} |
} |
677 |
|
|
678 |
JNIEXPORT void JNICALL |
JNIEXPORT void JNICALL |
679 |
Java_gnu_java_awt_peer_gtk_GtkClipboard_selectionGet |
Java_gnu_java_awt_peer_gtk_GtkSelection_requestURIs (JNIEnv *env, jobject obj) |
|
(JNIEnv *env, jclass clazz __attribute__((unused))) |
|
680 |
{ |
{ |
681 |
GdkWindow *owner; |
GdkAtom uri_atom; |
682 |
|
jobject selection_obj; |
683 |
|
selection_obj = (*env)->NewGlobalRef(env, obj); |
684 |
|
if (selection_obj == NULL) |
685 |
|
return; |
686 |
|
|
687 |
|
if (urisAvailableID == NULL) |
688 |
|
{ |
689 |
|
jclass gtk_selection_class; |
690 |
|
gtk_selection_class = (*env)->GetObjectClass (env, selection_obj); |
691 |
|
urisAvailableID = (*env)->GetMethodID (env, gtk_selection_class, |
692 |
|
"urisAvailable", |
693 |
|
"([Ljava/lang/String;)V"); |
694 |
|
if (urisAvailableID == NULL) |
695 |
|
return; |
696 |
|
} |
697 |
|
|
698 |
|
/* There is no real request_uris so we have to make one ourselves. */ |
699 |
gdk_threads_enter (); |
gdk_threads_enter (); |
700 |
|
uri_atom = gdk_atom_intern ("text/uri-list", FALSE); |
701 |
|
gtk_clipboard_request_contents (clipboard, |
702 |
|
uri_atom, |
703 |
|
cp_gtk_clipboard_uris_received, |
704 |
|
(gpointer) selection_obj); |
705 |
|
gdk_threads_leave (); |
706 |
|
} |
707 |
|
|
708 |
/* if we already own the clipboard, we need to tell the old data object |
static jmethodID bytesAvailableID; |
|
that we're no longer going to be using him */ |
|
|
owner = gdk_selection_owner_get (GDK_SELECTION_PRIMARY); |
|
|
if (owner && owner == clipboard->window) |
|
|
(*env)->CallVoidMethod (env, cb_obj, selectionClearID); |
|
|
|
|
|
gtk_selection_owner_set (clipboard, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME); |
|
709 |
|
|
710 |
gdk_threads_leave (); |
static void |
711 |
|
cp_gtk_clipboard_bytes_received (GtkClipboard *clipboard |
712 |
|
__attribute__((unused)), |
713 |
|
GtkSelectionData *selection_data, |
714 |
|
gpointer selection) |
715 |
|
{ |
716 |
|
jbyteArray bytes = NULL; |
717 |
|
jobject selection_obj = (jobject) selection; |
718 |
|
JNIEnv *env = cp_gtk_gdk_env (); |
719 |
|
|
720 |
|
if (selection_data != NULL && selection_data->length > 0) |
721 |
|
{ |
722 |
|
bytes = (*env)->NewByteArray (env, selection_data->length); |
723 |
|
if (bytes != NULL) |
724 |
|
(*env)->SetByteArrayRegion(env, bytes, 0, selection_data->length, |
725 |
|
(jbyte *) selection_data->data); |
726 |
|
} |
727 |
|
|
728 |
|
(*env)->CallVoidMethod (env, selection_obj, |
729 |
|
bytesAvailableID, |
730 |
|
bytes); |
731 |
|
(*env)->DeleteGlobalRef (env, selection_obj); |
732 |
} |
} |
733 |
|
|
734 |
static gint |
JNIEXPORT void JNICALL |
735 |
selection_clear_cb (GtkWidget *widget __attribute__((unused)), |
Java_gnu_java_awt_peer_gtk_GtkSelection_requestBytes (JNIEnv *env, |
736 |
GdkEventSelection *event __attribute__((unused))) |
jobject obj, |
737 |
|
jstring target_string) |
738 |
{ |
{ |
739 |
gdk_threads_leave (); |
int len; |
740 |
|
const gchar *target_text; |
741 |
|
GdkAtom target_atom; |
742 |
|
jobject selection_obj; |
743 |
|
selection_obj = (*env)->NewGlobalRef(env, obj); |
744 |
|
if (selection_obj == NULL) |
745 |
|
return; |
746 |
|
|
747 |
|
if (bytesAvailableID == NULL) |
748 |
|
{ |
749 |
|
jclass gtk_selection_class; |
750 |
|
gtk_selection_class = (*env)->GetObjectClass (env, selection_obj); |
751 |
|
bytesAvailableID = (*env)->GetMethodID (env, gtk_selection_class, |
752 |
|
"bytesAvailable", |
753 |
|
"([B)V"); |
754 |
|
if (bytesAvailableID == NULL) |
755 |
|
return; |
756 |
|
} |
757 |
|
|
758 |
(*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), cb_obj, selectionClearID); |
len = (*env)->GetStringUTFLength (env, target_string); |
759 |
|
if (len == -1) |
760 |
|
return; |
761 |
|
target_text = (*env)->GetStringUTFChars (env, target_string, NULL); |
762 |
|
if (target_text == NULL) |
763 |
|
return; |
764 |
|
|
765 |
gdk_threads_enter (); |
gdk_threads_enter (); |
766 |
|
target_atom = gdk_atom_intern (target_text, FALSE); |
767 |
|
gtk_clipboard_request_contents (clipboard, |
768 |
|
target_atom, |
769 |
|
cp_gtk_clipboard_bytes_received, |
770 |
|
(gpointer) selection_obj); |
771 |
|
gdk_threads_leave (); |
772 |
|
|
773 |
return TRUE; |
(*env)->ReleaseStringUTFChars (env, target_string, target_text); |
774 |
} |
} |