1 /* gtkselection.c -- Native C functions for GtkSelection class using gtk+.
2 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 #include "jcl.h"
40 #include "gtkpeer.h"
41 #include "gnu_java_awt_peer_gtk_GtkSelection.h"
42
43 static jmethodID mimeTypesAvailableID;
44
45 /* Note this is actually just a GtkClipboardReceivedFunc, not a real
46 GtkClipboardTargetsReceivedFunc, see requestMimeTypes. */
47 static void
clipboard_targets_received(GtkClipboard * clipboard,GtkSelectionData * target_data,gpointer selection)48 clipboard_targets_received (GtkClipboard *clipboard
49 __attribute__((unused)),
50 GtkSelectionData *target_data,
51 gpointer selection)
52 {
53 GdkAtom *targets = NULL;
54 gint targets_len = 0;
55 gchar **target_strings = NULL;
56 jobjectArray strings = NULL;
57 int strings_len = 0;
58 gboolean include_text = FALSE;
59 gboolean include_image = FALSE;
60 gboolean include_uris = FALSE;
61 jobject selection_obj = (jobject) selection;
62 JNIEnv *env = cp_gtk_gdk_env ();
63
64 if (target_data != NULL && target_data->length > 0)
65 {
66 include_text = gtk_selection_data_targets_include_text (target_data);
67
68 #if GTK_MINOR_VERSION > 4
69 include_image = gtk_selection_data_targets_include_image (target_data,
70 TRUE);
71 #endif
72 if (gtk_selection_data_get_targets (target_data, &targets, &targets_len))
73 {
74 int i;
75 GdkAtom uri_list_atom = gdk_atom_intern ("text/uri-list", FALSE);
76 target_strings = g_new (gchar*, targets_len);
77 if (target_strings != NULL)
78 for (i = 0; i < targets_len; i++)
79 {
80 gchar *name = gdk_atom_name (targets[i]);
81 if (strchr (name, '/') != NULL)
82 {
83 target_strings[i] = name;
84 strings_len++;
85 if (! include_uris && targets[i] == uri_list_atom)
86 include_uris = TRUE;
87 }
88 else
89 target_strings[i] = NULL;
90 }
91 }
92
93 if (target_strings != NULL)
94 {
95 int i = 0, j = 0;
96 jclass stringClass;
97
98 if (include_text)
99 strings_len++;
100 if (include_image)
101 strings_len++;
102 if (include_uris)
103 strings_len++;
104
105 stringClass = (*env)->FindClass (env, "java/lang/String");
106 strings = (*env)->NewObjectArray (env, strings_len, stringClass,
107 NULL);
108 (*env)->DeleteLocalRef(env, stringClass);
109
110 if (strings != NULL)
111 {
112 if (include_text)
113 (*env)->SetObjectArrayElement (env, strings, i++,
114 cp_gtk_stringTarget);
115 if (include_image)
116 (*env)->SetObjectArrayElement (env, strings, i++,
117 cp_gtk_imageTarget);
118 if (include_uris)
119 (*env)->SetObjectArrayElement (env, strings, i++,
120 cp_gtk_filesTarget);
121
122 while(i < strings_len)
123 {
124 if (target_strings[j] == NULL)
125 j++;
126 else
127 {
128 jstring string;
129 string = (*env)->NewStringUTF (env,
130 target_strings[j++]);
131 if (string == NULL)
132 break;
133 (*env)->SetObjectArrayElement (env, strings, i++,
134 string);
135 (*env)->DeleteLocalRef (env, string);
136 }
137 }
138
139 (*env)->DeleteLocalRef(env, strings);
140 }
141
142 for (i = 0; i < targets_len; i++)
143 g_free (target_strings[i]);
144 g_free (target_strings);
145 }
146 }
147
148 (*env)->CallVoidMethod (env, selection_obj,
149 mimeTypesAvailableID,
150 strings);
151 (*env)->DeleteGlobalRef (env, selection_obj);
152 }
153
154 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkSelection_requestMimeTypes(JNIEnv * env,jobject selection,jboolean clipboard)155 Java_gnu_java_awt_peer_gtk_GtkSelection_requestMimeTypes
156 (JNIEnv *env, jobject selection, jboolean clipboard)
157 {
158 jobject selection_obj;
159 GtkClipboard *gtk_clipboard;
160 selection_obj = (*env)->NewGlobalRef(env, selection);
161 if (selection_obj == NULL)
162 return;
163
164 if (mimeTypesAvailableID == NULL)
165 {
166 jclass gtk_selection_class;
167 gtk_selection_class = (*env)->GetObjectClass (env, selection_obj);
168 mimeTypesAvailableID = (*env)->GetMethodID (env, gtk_selection_class,
169 "mimeTypesAvailable",
170 "([Ljava/lang/String;)V");
171 if (mimeTypesAvailableID == NULL)
172 return;
173 }
174
175 if (clipboard)
176 gtk_clipboard = cp_gtk_clipboard;
177 else
178 gtk_clipboard = cp_gtk_selection;
179
180 /* We would have liked to call gtk_clipboard_request_targets ()
181 since that is more general. But the result of that, an array of
182 GdkAtoms, cannot be used with the
183 gtk_selection_data_targets_include_<x> functions (despite what
184 the name suggests). */
185 gdk_threads_enter ();
186 gtk_clipboard_request_contents (gtk_clipboard,
187 gdk_atom_intern ("TARGETS", FALSE),
188 clipboard_targets_received,
189 (gpointer) selection_obj);
190 gdk_threads_leave ();
191 }
192
193
194 static jmethodID textAvailableID;
195
196 static void
clipboard_text_received(GtkClipboard * clipboard,const gchar * text,gpointer selection)197 clipboard_text_received (GtkClipboard *clipboard
198 __attribute__((unused)),
199 const gchar *text,
200 gpointer selection)
201 {
202 jstring string;
203 jobject selection_obj = (jobject) selection;
204
205 JNIEnv *env = cp_gtk_gdk_env ();
206 if (text != NULL)
207 string = (*env)->NewStringUTF (env, text);
208 else
209 string = NULL;
210
211 (*env)->CallVoidMethod (env, selection_obj,
212 textAvailableID,
213 string);
214 (*env)->DeleteGlobalRef (env, selection_obj);
215
216 if (string != NULL)
217 (*env)->DeleteLocalRef (env, string);
218
219 }
220
221 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkSelection_requestText(JNIEnv * env,jobject selection,jboolean clipboard)222 Java_gnu_java_awt_peer_gtk_GtkSelection_requestText
223 (JNIEnv *env, jobject selection, jboolean clipboard)
224 {
225 jobject selection_obj;
226 GtkClipboard *gtk_clipboard;
227 selection_obj = (*env)->NewGlobalRef(env, selection);
228 if (selection_obj == NULL)
229 return;
230
231 if (textAvailableID == NULL)
232 {
233 jclass gtk_selection_class;
234 gtk_selection_class = (*env)->GetObjectClass (env, selection_obj);
235 textAvailableID = (*env)->GetMethodID (env, gtk_selection_class,
236 "textAvailable",
237 "(Ljava/lang/String;)V");
238 if (textAvailableID == NULL)
239 return;
240 }
241
242 if (clipboard)
243 gtk_clipboard = cp_gtk_clipboard;
244 else
245 gtk_clipboard = cp_gtk_selection;
246
247 gdk_threads_enter ();
248 gtk_clipboard_request_text (gtk_clipboard,
249 clipboard_text_received,
250 (gpointer) selection_obj);
251 gdk_threads_leave ();
252 }
253
254 static jmethodID imageAvailableID;
255
256 static void
clipboard_image_received(GtkClipboard * clipboard,GdkPixbuf * pixbuf,gpointer selection)257 clipboard_image_received (GtkClipboard *clipboard
258 __attribute__((unused)),
259 GdkPixbuf *pixbuf,
260 gpointer selection)
261 {
262 jobject pointer = NULL;
263 jobject selection_obj = (jobject) selection;
264 JNIEnv *env = cp_gtk_gdk_env ();
265
266 if (pixbuf != NULL)
267 {
268 g_object_ref (pixbuf);
269 pointer = JCL_NewRawDataObject (env, (void *) pixbuf);
270 }
271
272 (*env)->CallVoidMethod (env, selection_obj,
273 imageAvailableID,
274 pointer);
275 (*env)->DeleteGlobalRef (env, selection_obj);
276 }
277
278 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkSelection_requestImage(JNIEnv * env,jobject obj,jboolean clipboard)279 Java_gnu_java_awt_peer_gtk_GtkSelection_requestImage (JNIEnv *env,
280 jobject obj,
281 jboolean clipboard)
282 {
283 jobject selection_obj;
284 GtkClipboard *gtk_clipboard;
285 selection_obj = (*env)->NewGlobalRef(env, obj);
286 if (selection_obj == NULL)
287 return;
288
289 if (imageAvailableID == NULL)
290 {
291 jclass gtk_selection_class;
292 gtk_selection_class = (*env)->GetObjectClass (env, selection_obj);
293 imageAvailableID = (*env)->GetMethodID (env, gtk_selection_class,
294 "imageAvailable",
295 "(Lgnu/classpath/Pointer;)V");
296 if (imageAvailableID == NULL)
297 return;
298 }
299
300 if (clipboard)
301 gtk_clipboard = cp_gtk_clipboard;
302 else
303 gtk_clipboard = cp_gtk_selection;
304
305 #if GTK_MINOR_VERSION > 4
306 gdk_threads_enter ();
307 gtk_clipboard_request_image (gtk_clipboard,
308 clipboard_image_received,
309 (gpointer) selection_obj);
310 gdk_threads_leave ();
311 #else
312 clipboard_image_received (gtk_clipboard, NULL, (gpointer) selection_obj);
313 #endif
314 }
315
316 static jmethodID urisAvailableID;
317
318 static void
clipboard_uris_received(GtkClipboard * clipboard,GtkSelectionData * uri_data,gpointer selection)319 clipboard_uris_received (GtkClipboard *clipboard
320 __attribute__((unused)),
321 GtkSelectionData *uri_data,
322 gpointer selection)
323 {
324 gchar **uris = NULL;
325 jobjectArray strings = NULL;
326 jobject selection_obj = (jobject) selection;
327 JNIEnv *env = cp_gtk_gdk_env ();
328
329 #if GTK_MINOR_VERSION > 4
330 if (uri_data != NULL)
331 uris = gtk_selection_data_get_uris (uri_data);
332 #else
333 if (uri_data != NULL)
334 uris = NULL;
335 #endif
336
337 if (uris != NULL)
338 {
339 int len, i;
340 gchar **count = uris;
341 jclass stringClass = (*env)->FindClass (env, "java/lang/String");
342
343 len = 0;
344 while (count[len])
345 len++;
346
347 strings = (*env)->NewObjectArray (env, len, stringClass, NULL);
348 (*env)->DeleteLocalRef(env, stringClass);
349
350 if (strings != NULL)
351 {
352 for (i = 0; i < len; i++)
353 {
354 jstring string = (*env)->NewStringUTF (env, uris[i]);
355 if (string == NULL)
356 break;
357 (*env)->SetObjectArrayElement (env, strings, i, string);
358 (*env)->DeleteLocalRef (env, string);
359 }
360
361 (*env)->DeleteLocalRef(env, strings);
362 }
363 g_strfreev (uris);
364 }
365
366 (*env)->CallVoidMethod (env, selection_obj,
367 urisAvailableID,
368 strings);
369 (*env)->DeleteGlobalRef (env, selection_obj);
370 }
371
372 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkSelection_requestURIs(JNIEnv * env,jobject obj,jboolean clipboard)373 Java_gnu_java_awt_peer_gtk_GtkSelection_requestURIs (JNIEnv *env,
374 jobject obj,
375 jboolean clipboard)
376 {
377 #if GTK_MINOR_VERSION > 4
378 GdkAtom uri_atom;
379 #endif
380 jobject selection_obj;
381 GtkClipboard *gtk_clipboard;
382 selection_obj = (*env)->NewGlobalRef(env, obj);
383 if (selection_obj == NULL)
384 return;
385
386 if (urisAvailableID == NULL)
387 {
388 jclass gtk_selection_class;
389 gtk_selection_class = (*env)->GetObjectClass (env, selection_obj);
390 urisAvailableID = (*env)->GetMethodID (env, gtk_selection_class,
391 "urisAvailable",
392 "([Ljava/lang/String;)V");
393 if (urisAvailableID == NULL)
394 return;
395 }
396
397 if (clipboard)
398 gtk_clipboard = cp_gtk_clipboard;
399 else
400 gtk_clipboard = cp_gtk_selection;
401
402 #if GTK_MINOR_VERSION > 4
403 /* There is no real request_uris so we have to make one ourselves. */
404 gdk_threads_enter ();
405 uri_atom = gdk_atom_intern ("text/uri-list", FALSE);
406 gtk_clipboard_request_contents (gtk_clipboard,
407 uri_atom,
408 clipboard_uris_received,
409 (gpointer) selection_obj);
410 gdk_threads_leave ();
411 #else
412 clipboard_uris_received (gtk_clipboard, NULL, (gpointer) selection_obj);
413 #endif
414 }
415
416 static jmethodID bytesAvailableID;
417
418 static void
clipboard_bytes_received(GtkClipboard * clipboard,GtkSelectionData * selection_data,gpointer selection)419 clipboard_bytes_received (GtkClipboard *clipboard
420 __attribute__((unused)),
421 GtkSelectionData *selection_data,
422 gpointer selection)
423 {
424 jbyteArray bytes = NULL;
425 jobject selection_obj = (jobject) selection;
426 JNIEnv *env = cp_gtk_gdk_env ();
427
428 if (selection_data != NULL && selection_data->length > 0)
429 {
430 bytes = (*env)->NewByteArray (env, selection_data->length);
431 if (bytes != NULL)
432 (*env)->SetByteArrayRegion(env, bytes, 0, selection_data->length,
433 (jbyte *) selection_data->data);
434 }
435
436 (*env)->CallVoidMethod (env, selection_obj,
437 bytesAvailableID,
438 bytes);
439 (*env)->DeleteGlobalRef (env, selection_obj);
440 }
441
442 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkSelection_requestBytes(JNIEnv * env,jobject obj,jboolean clipboard,jstring target_string)443 Java_gnu_java_awt_peer_gtk_GtkSelection_requestBytes (JNIEnv *env,
444 jobject obj,
445 jboolean clipboard,
446 jstring target_string)
447 {
448 int len;
449 const gchar *target_text;
450 GdkAtom target_atom;
451 jobject selection_obj;
452 GtkClipboard *gtk_clipboard;
453 selection_obj = (*env)->NewGlobalRef(env, obj);
454 if (selection_obj == NULL)
455 return;
456
457 if (bytesAvailableID == NULL)
458 {
459 jclass gtk_selection_class;
460 gtk_selection_class = (*env)->GetObjectClass (env, selection_obj);
461 bytesAvailableID = (*env)->GetMethodID (env, gtk_selection_class,
462 "bytesAvailable",
463 "([B)V");
464 if (bytesAvailableID == NULL)
465 return;
466 }
467
468 len = (*env)->GetStringUTFLength (env, target_string);
469 if (len == -1)
470 return;
471 target_text = (*env)->GetStringUTFChars (env, target_string, NULL);
472 if (target_text == NULL)
473 return;
474
475 if (clipboard)
476 gtk_clipboard = cp_gtk_clipboard;
477 else
478 gtk_clipboard = cp_gtk_selection;
479
480 gdk_threads_enter ();
481 target_atom = gdk_atom_intern (target_text, FALSE);
482 gtk_clipboard_request_contents (gtk_clipboard,
483 target_atom,
484 clipboard_bytes_received,
485 (gpointer) selection_obj);
486 gdk_threads_leave ();
487
488 (*env)->ReleaseStringUTFChars (env, target_string, target_text);
489 }
490