2 Copyright (C) 1998, 1999, 2005 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)
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
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
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. */
41 #include "gnu_java_awt_peer_gtk_GtkClipboard.h"
43 #define OBJECT_TARGET 1
45 #define IMAGE_TARGET 3
48 /* The clipboard and standard (string targets) shared with GtkSelection. */
49 GtkClipboard *cp_gtk_clipboard;
51 jstring cp_gtk_stringTarget;
52 jstring cp_gtk_imageTarget;
53 jstring cp_gtk_filesTarget;
55 /* Simple id to keep track of the selection we are currently managing. */
56 static gint current_selection = 0;
58 /* Whether we "own" the clipboard. And may clear it. */
61 static jclass gtk_clipboard_class;
62 static jmethodID setSystemContentsID;
64 static jobject gtk_clipboard_instance = NULL;
65 static jmethodID provideContentID;
66 static jmethodID provideTextID;
67 static jmethodID provideImageID;
68 static jmethodID provideURIsID;
70 /* Called when clipboard owner changes. Used to update available targets. */
71 #if GTK_MINOR_VERSION > 4
73 clipboard_owner_change_cb (GtkClipboard *clipboard __attribute__((unused)),
74 GdkEvent *event __attribute__((unused)),
75 gpointer user_data __attribute__((unused)))
77 /* These are only interesting when we are not the owner. Otherwise
78 we will have the set and clear functions doing the updating. */
79 JNIEnv *env = cp_gtk_gdk_env ();
81 (*env)->CallStaticVoidMethod (env, gtk_clipboard_class,
86 JNIEXPORT jboolean JNICALL
87 Java_gnu_java_awt_peer_gtk_GtkClipboard_initNativeState (JNIEnv *env,
96 gtk_clipboard_class = gtkclipboard;
97 setSystemContentsID = (*env)->GetStaticMethodID (env, gtk_clipboard_class,
100 if (setSystemContentsID == NULL)
103 cp_gtk_stringTarget = (*env)->NewGlobalRef(env, string);
104 cp_gtk_imageTarget = (*env)->NewGlobalRef(env, image);
105 cp_gtk_filesTarget = (*env)->NewGlobalRef(env, files);
107 gdk_threads_enter ();
108 cp_gtk_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
110 display = gtk_clipboard_get_display (cp_gtk_clipboard);
111 /* Check for support for clipboard owner changes. */
112 #if GTK_MINOR_VERSION > 4
113 if (gdk_display_supports_selection_notification (display))
115 g_signal_connect (cp_gtk_clipboard, "owner-change",
116 G_CALLBACK (clipboard_owner_change_cb), NULL);
117 gdk_display_request_selection_notification (display,
118 GDK_SELECTION_CLIPBOARD);
119 can_cache = JNI_TRUE;
123 can_cache = JNI_FALSE;
124 gdk_threads_leave ();
130 clipboard_get_func (GtkClipboard *clipboard __attribute__((unused)),
131 GtkSelectionData *selection,
133 gpointer user_data __attribute__((unused)))
135 JNIEnv *env = cp_gtk_gdk_env ();
137 if (info == OBJECT_TARGET)
139 const gchar *target_name;
140 jstring target_string;
145 target_name = gdk_atom_name (selection->target);
146 if (target_name == NULL)
148 target_string = (*env)->NewStringUTF (env, target_name);
149 if (target_string == NULL)
151 bytes = (*env)->CallObjectMethod(env,
152 gtk_clipboard_instance,
157 len = (*env)->GetArrayLength(env, bytes);
160 barray = (*env)->GetByteArrayElements(env, bytes, NULL);
163 gtk_selection_data_set (selection, selection->target, 8,
164 (guchar *) barray, len);
166 (*env)->ReleaseByteArrayElements(env, bytes, barray, 0);
169 else if (info == TEXT_TARGET)
174 string = (*env)->CallObjectMethod(env,
175 gtk_clipboard_instance,
179 len = (*env)->GetStringUTFLength (env, string);
182 text = (*env)->GetStringUTFChars (env, string, NULL);
186 gtk_selection_data_set_text (selection, text, len);
187 (*env)->ReleaseStringUTFChars (env, string, text);
189 /* Images and URIs/Files support only available with gtk+2.6 or higher. */
190 #if GTK_MINOR_VERSION > 4
191 else if (info == IMAGE_TARGET)
194 GdkPixbuf *pixbuf = NULL;
196 gtkimage = (*env)->CallObjectMethod(env,
197 gtk_clipboard_instance,
199 if (gtkimage == NULL)
202 pixbuf = cp_gtk_image_get_pixbuf (env, gtkimage);
205 gtk_selection_data_set_pixbuf (selection, pixbuf);
207 /* if the GtkImage is offscreen, this is a temporary pixbuf
208 which should be thrown out. */
209 if(cp_gtk_image_is_offscreen (env, gtkimage) == JNI_TRUE)
210 gdk_pixbuf_unref (pixbuf);
213 else if (info == URI_TARGET)
220 uris = (*env)->CallObjectMethod(env,
221 gtk_clipboard_instance,
225 count = (*env)->GetArrayLength (env, uris);
229 list = (gchar **) JCL_malloc (env, (count + 1) * sizeof (gchar *));
230 for (i = 0; i < count; i++)
235 /* Mark NULL in so case of some error we can find the end. */
237 uri = (*env)->GetObjectArrayElement (env, uris, i);
240 text = (*env)->GetStringUTFChars (env, uri, NULL);
243 list[i] = strdup (text);
244 (*env)->ReleaseStringUTFChars (env, uri, text);
250 gtk_selection_data_set_uris (selection, list);
253 for (i = 0; list[i] != NULL; i++)
255 JCL_free (env, list);
261 clipboard_clear_func (GtkClipboard *clipboard __attribute__((unused)),
264 if (owner && GPOINTER_TO_INT(user_data) == current_selection)
266 JNIEnv *env = cp_gtk_gdk_env();
268 (*env)->CallStaticVoidMethod (env, gtk_clipboard_class,
269 setSystemContentsID);
273 JNIEXPORT void JNICALL
274 Java_gnu_java_awt_peer_gtk_GtkClipboard_advertiseContent
277 jobjectArray mime_array,
278 #if GTK_MINOR_VERSION > 4
279 jboolean add_text, jboolean add_images, jboolean add_uris)
281 jboolean add_text __attribute__((unused)),
282 jboolean add_images __attribute__((unused)),
283 jboolean add_uris __attribute__((unused)))
286 GtkTargetList *target_list;
288 GtkTargetEntry *targets;
291 gdk_threads_enter ();
292 target_list = gtk_target_list_new (NULL, 0);
294 if (mime_array != NULL)
296 n = (*env)->GetArrayLength (env, mime_array);
297 for (i = 0; i < n; i++)
303 target = (*env)->GetObjectArrayElement (env, mime_array, i);
306 text = (*env)->GetStringUTFChars (env, target, NULL);
310 atom = gdk_atom_intern (text, FALSE);
311 gtk_target_list_add (target_list, atom, 0, OBJECT_TARGET);
313 (*env)->ReleaseStringUTFChars (env, target, text);
317 /* Add extra targets that gtk+ can provide/translate for us. */
318 #if GTK_MINOR_VERSION > 4
320 gtk_target_list_add_text_targets (target_list, TEXT_TARGET);
322 gtk_target_list_add_image_targets (target_list, IMAGE_TARGET, TRUE);
324 gtk_target_list_add_uri_targets (target_list, URI_TARGET);
327 gtk_target_list_add (target_list,
328 gdk_atom_intern ("STRING", FALSE),
333 /* Turn list into a target table. */
334 n = g_list_length (target_list->list);
337 targets = g_new (GtkTargetEntry, n);
338 for (list = target_list->list, i = 0;
340 list = list->next, i++)
342 GtkTargetPair *pair = (GtkTargetPair *) list->data;
343 targets[i].target = gdk_atom_name (pair->target);
344 targets[i].flags = pair->flags;
345 targets[i].info = pair->info;
348 /* Set the targets plus callback functions and ask for the clipboard
349 to be stored when the application exists if supported. */
351 if (gtk_clipboard_set_with_data (cp_gtk_clipboard, targets, n,
353 clipboard_clear_func,
354 GINT_TO_POINTER(current_selection)))
357 if (gtk_clipboard_instance == NULL)
359 JNIEnv *env = cp_gtk_gdk_env ();
360 gtk_clipboard_instance = (*env)->NewGlobalRef(env, instance);
363 = (*env)->GetMethodID (env, gtk_clipboard_class,
365 "(Ljava/lang/String;)[B");
366 if (provideContentID == NULL)
370 = (*env)->GetMethodID (env, gtk_clipboard_class,
371 "provideText", "()Ljava/lang/String;");
372 if (provideTextID == NULL)
376 = (*env)->GetMethodID (env, gtk_clipboard_class,
378 "()Lgnu/java/awt/peer/gtk/GtkImage;");
379 if (provideImageID == NULL)
383 = (*env)->GetMethodID (env, gtk_clipboard_class,
385 "()[Ljava/lang/String;");
386 if (provideURIsID == NULL)
389 #if GTK_MINOR_VERSION > 4
390 gtk_clipboard_set_can_store (cp_gtk_clipboard, NULL, 0);
396 (*env)->CallStaticVoidMethod (env, gtk_clipboard_class,
397 setSystemContentsID);
400 for (i = 0; i < n; i++)
401 g_free (targets[i].target);
406 gtk_clipboard_clear (cp_gtk_clipboard);
410 gtk_target_list_unref (target_list);
411 gdk_threads_leave ();