Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkClipboard.c
blobcb2c87238b28158059110a8294000ef11235d440
1 /* gtkclipboard.c
2 Copyright (C) 1998, 1999, 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 #include "jcl.h"
40 #include "gtkpeer.h"
41 #include "gnu_java_awt_peer_gtk_GtkClipboard.h"
43 #define OBJECT_TARGET 1
44 #define TEXT_TARGET 2
45 #define IMAGE_TARGET 3
46 #define URI_TARGET 4
48 /* The clipboard and selection plus corresponding GtkClipboard objects. */
49 GtkClipboard *cp_gtk_clipboard;
50 GtkClipboard *cp_gtk_selection;
52 jobject cp_gtk_clipboard_instance;
53 jobject cp_gtk_selection_instance;
55 /* Standard (string targets) shared with GtkSelection. */
56 jstring cp_gtk_stringTarget;
57 jstring cp_gtk_imageTarget;
58 jstring cp_gtk_filesTarget;
60 static jclass gtk_clipboard_class;
62 static jmethodID setSystemContentsID;
63 static jmethodID provideContentID;
64 static jmethodID provideTextID;
65 static jmethodID provideImageID;
66 static jmethodID provideURIsID;
68 /* Called when clipboard owner changes. Used to update available targets. */
69 #if GTK_MINOR_VERSION > 4
70 static void
71 clipboard_owner_change_cb (GtkClipboard *clipboard,
72 GdkEvent *event __attribute__((unused)),
73 gpointer user_data __attribute__((unused)))
75 JNIEnv *env = cp_gtk_gdk_env ();
76 if (clipboard == cp_gtk_clipboard)
77 (*env)->CallVoidMethod (env, cp_gtk_clipboard_instance,
78 setSystemContentsID, JNI_FALSE);
79 else
80 (*env)->CallVoidMethod (env, cp_gtk_selection_instance,
81 setSystemContentsID, JNI_FALSE);
84 #endif
86 JNIEXPORT jboolean JNICALL
87 Java_gnu_java_awt_peer_gtk_GtkClipboard_initNativeState (JNIEnv *env,
88 jclass clz,
89 jobject gtkclipboard,
90 jobject gtkselection,
91 jstring string,
92 jstring image,
93 jstring files)
95 GdkDisplay* display;
96 jboolean can_cache;
98 gtk_clipboard_class = clz;
99 setSystemContentsID = (*env)->GetMethodID (env, gtk_clipboard_class,
100 "setSystemContents",
101 "(Z)V");
102 if (setSystemContentsID == NULL)
103 return JNI_FALSE;
105 provideContentID = (*env)->GetMethodID (env, gtk_clipboard_class,
106 "provideContent",
107 "(Ljava/lang/String;)[B");
108 if (provideContentID == NULL)
109 return JNI_FALSE;
111 provideTextID = (*env)->GetMethodID (env, gtk_clipboard_class,
112 "provideText",
113 "()Ljava/lang/String;");
114 if (provideTextID == NULL)
115 return JNI_FALSE;
117 provideImageID = (*env)->GetMethodID (env, gtk_clipboard_class,
118 "provideImage",
119 "()Lgnu/java/awt/peer/gtk/GtkImage;");
120 if (provideImageID == NULL)
121 return JNI_FALSE;
123 provideURIsID = (*env)->GetMethodID (env, gtk_clipboard_class,
124 "provideURIs",
125 "()[Ljava/lang/String;");
126 if (provideURIsID == NULL)
127 return JNI_FALSE;
129 cp_gtk_clipboard_instance = (*env)->NewGlobalRef(env, gtkclipboard);
130 cp_gtk_selection_instance = (*env)->NewGlobalRef(env, gtkselection);
132 cp_gtk_stringTarget = (*env)->NewGlobalRef(env, string);
133 cp_gtk_imageTarget = (*env)->NewGlobalRef(env, image);
134 cp_gtk_filesTarget = (*env)->NewGlobalRef(env, files);
136 gdk_threads_enter ();
137 cp_gtk_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
138 cp_gtk_selection = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
140 display = gtk_clipboard_get_display (cp_gtk_clipboard);
141 /* Check for support for clipboard owner changes. */
142 #if GTK_MINOR_VERSION > 4
143 if (gdk_display_supports_selection_notification (display))
145 g_signal_connect (cp_gtk_clipboard, "owner-change",
146 G_CALLBACK (clipboard_owner_change_cb), NULL);
147 g_signal_connect (cp_gtk_selection, "owner-change",
148 G_CALLBACK (clipboard_owner_change_cb), NULL);
149 gdk_display_request_selection_notification (display,
150 GDK_SELECTION_CLIPBOARD);
151 gdk_display_request_selection_notification (display,
152 GDK_SELECTION_PRIMARY);
153 can_cache = JNI_TRUE;
155 else
156 #endif
157 can_cache = JNI_FALSE;
159 gdk_threads_leave ();
161 return can_cache;
164 static void
165 clipboard_get_func (GtkClipboard *clipboard,
166 GtkSelectionData *selection,
167 guint info,
168 gpointer user_data __attribute__((unused)))
170 jobject gtk_clipboard_instance;
171 JNIEnv *env = cp_gtk_gdk_env ();
173 if (clipboard == cp_gtk_clipboard)
174 gtk_clipboard_instance = cp_gtk_clipboard_instance;
175 else
176 gtk_clipboard_instance = cp_gtk_selection_instance;
178 if (info == OBJECT_TARGET)
180 const gchar *target_name;
181 jstring target_string;
182 jbyteArray bytes;
183 jint len;
184 jbyte *barray;
186 target_name = gdk_atom_name (selection->target);
187 if (target_name == NULL)
188 return;
189 target_string = (*env)->NewStringUTF (env, target_name);
190 if (target_string == NULL)
191 return;
192 bytes = (*env)->CallObjectMethod(env,
193 gtk_clipboard_instance,
194 provideContentID,
195 target_string);
196 if (bytes == NULL)
197 return;
198 len = (*env)->GetArrayLength(env, bytes);
199 if (len <= 0)
200 return;
201 barray = (*env)->GetByteArrayElements(env, bytes, NULL);
202 if (barray == NULL)
203 return;
204 gtk_selection_data_set (selection, selection->target, 8,
205 (guchar *) barray, len);
207 (*env)->ReleaseByteArrayElements(env, bytes, barray, 0);
210 else if (info == TEXT_TARGET)
212 jstring string;
213 const gchar *text;
214 int len;
215 string = (*env)->CallObjectMethod(env,
216 gtk_clipboard_instance,
217 provideTextID);
218 if (string == NULL)
219 return;
220 len = (*env)->GetStringUTFLength (env, string);
221 if (len == -1)
222 return;
223 text = (*env)->GetStringUTFChars (env, string, NULL);
224 if (text == NULL)
225 return;
227 gtk_selection_data_set_text (selection, text, len);
228 (*env)->ReleaseStringUTFChars (env, string, text);
230 /* Images and URIs/Files support only available with gtk+2.6 or higher. */
231 #if GTK_MINOR_VERSION > 4
232 else if (info == IMAGE_TARGET)
234 jobject gtkimage;
235 GdkPixbuf *pixbuf = NULL;
237 gtkimage = (*env)->CallObjectMethod(env,
238 gtk_clipboard_instance,
239 provideImageID);
240 if (gtkimage == NULL)
241 return;
243 pixbuf = cp_gtk_image_get_pixbuf (env, gtkimage);
244 if (pixbuf != NULL)
246 gtk_selection_data_set_pixbuf (selection, pixbuf);
248 /* if the GtkImage is offscreen, this is a temporary pixbuf
249 which should be thrown out. */
250 if(cp_gtk_image_is_offscreen (env, gtkimage) == JNI_TRUE)
251 gdk_pixbuf_unref (pixbuf);
254 else if (info == URI_TARGET)
256 jobjectArray uris;
257 jint count;
258 int i;
259 gchar **list;
261 uris = (*env)->CallObjectMethod(env,
262 gtk_clipboard_instance,
263 provideURIsID);
264 if (uris == NULL)
265 return;
266 count = (*env)->GetArrayLength (env, uris);
267 if (count <= 0)
268 return;
270 list = (gchar **) JCL_malloc (env, (count + 1) * sizeof (gchar *));
271 for (i = 0; i < count; i++)
273 const char *text;
274 jstring uri;
276 /* Mark NULL in so case of some error we can find the end. */
277 list[i] = NULL;
278 uri = (*env)->GetObjectArrayElement (env, uris, i);
279 if (uri == NULL)
280 break;
281 text = (*env)->GetStringUTFChars (env, uri, NULL);
282 if (text == NULL)
283 break;
284 list[i] = strdup (text);
285 (*env)->ReleaseStringUTFChars (env, uri, text);
288 if (i == count)
290 list[count] = NULL;
291 gtk_selection_data_set_uris (selection, list);
294 for (i = 0; list[i] != NULL; i++)
295 free (list[i]);
296 JCL_free (env, list);
298 #endif
301 static void
302 clipboard_clear_func (GtkClipboard *clipboard,
303 gpointer user_data __attribute__((unused)))
305 JNIEnv *env = cp_gtk_gdk_env();
306 if (clipboard == cp_gtk_clipboard)
307 (*env)->CallVoidMethod (env, cp_gtk_clipboard_instance,
308 setSystemContentsID, JNI_TRUE);
309 else
310 (*env)->CallVoidMethod (env, cp_gtk_selection_instance,
311 setSystemContentsID, JNI_TRUE);
315 JNIEXPORT void JNICALL
316 Java_gnu_java_awt_peer_gtk_GtkClipboard_advertiseContent
317 (JNIEnv *env,
318 jobject instance,
319 jobjectArray mime_array,
320 #if GTK_MINOR_VERSION > 4
321 jboolean add_text, jboolean add_images, jboolean add_uris)
322 #else
323 jboolean add_text __attribute__((unused)),
324 jboolean add_images __attribute__((unused)),
325 jboolean add_uris __attribute__((unused)))
326 #endif
328 GtkTargetList *target_list;
329 GList *list;
330 GtkTargetEntry *targets;
331 gint n, i;
333 gdk_threads_enter ();
334 target_list = gtk_target_list_new (NULL, 0);
336 if (mime_array != NULL)
338 n = (*env)->GetArrayLength (env, mime_array);
339 for (i = 0; i < n; i++)
341 const char *text;
342 jstring target;
343 GdkAtom atom;
345 target = (*env)->GetObjectArrayElement (env, mime_array, i);
346 if (target == NULL)
347 break;
348 text = (*env)->GetStringUTFChars (env, target, NULL);
349 if (text == NULL)
350 break;
352 atom = gdk_atom_intern (text, FALSE);
353 gtk_target_list_add (target_list, atom, 0, OBJECT_TARGET);
355 (*env)->ReleaseStringUTFChars (env, target, text);
359 /* Add extra targets that gtk+ can provide/translate for us. */
360 #if GTK_MINOR_VERSION > 4
361 if (add_text)
362 gtk_target_list_add_text_targets (target_list, TEXT_TARGET);
363 if (add_images)
364 gtk_target_list_add_image_targets (target_list, IMAGE_TARGET, TRUE);
365 if (add_uris)
366 gtk_target_list_add_uri_targets (target_list, URI_TARGET);
367 #else
368 if (add_text)
369 gtk_target_list_add (target_list,
370 gdk_atom_intern ("STRING", FALSE),
371 0, TEXT_TARGET);
372 #endif
375 /* Turn list into a target table. */
376 n = g_list_length (target_list->list);
377 if (n > 0)
379 targets = g_new (GtkTargetEntry, n);
380 for (list = target_list->list, i = 0;
381 list != NULL;
382 list = list->next, i++)
384 GtkTargetPair *pair = (GtkTargetPair *) list->data;
385 targets[i].target = gdk_atom_name (pair->target);
386 targets[i].flags = pair->flags;
387 targets[i].info = pair->info;
390 /* Set the targets plus callback functions and ask for the clipboard
391 to be stored when the application exists if supported. */
392 if ((*env)->IsSameObject(env, instance, cp_gtk_clipboard_instance))
394 if (gtk_clipboard_set_with_data (cp_gtk_clipboard, targets, n,
395 clipboard_get_func,
396 clipboard_clear_func,
397 NULL))
399 #if GTK_MINOR_VERSION > 4
400 gtk_clipboard_set_can_store (cp_gtk_clipboard, NULL, 0);
401 #endif
404 else
406 if (gtk_clipboard_set_with_data (cp_gtk_selection, targets, n,
407 clipboard_get_func,
408 clipboard_clear_func,
409 NULL))
411 #if GTK_MINOR_VERSION > 4
412 gtk_clipboard_set_can_store (cp_gtk_selection, NULL, 0);
413 #endif
417 for (i = 0; i < n; i++)
418 g_free (targets[i].target);
419 g_free (targets);
422 gtk_target_list_unref (target_list);
423 gdk_threads_leave ();