/[classpath]/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c
ViewVC logotype

Diff of /classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.7.2.3 by gnu_andrew, Tue Aug 2 20:12:39 2005 UTC revision 1.7.2.4 by gnu_andrew, Sat Sep 10 15:32:00 2005 UTC
# Line 1  Line 1 
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    
# Line 36  obligated to do so.  If you do not wish Line 36  obligated to do so.  If you do not wish
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    
43  static jmethodID stringSelectionReceivedID;  #define OBJECT_TARGET 1
44  static jmethodID stringSelectionHandlerID;  #define TEXT_TARGET   2
45  static jmethodID selectionClearID;  #define IMAGE_TARGET  3
46    #define URI_TARGET    4
47  static void selection_received_cb (GtkWidget *, GtkSelectionData *,  
48                                     guint, gpointer);  /* The clipboard and standard (string targets) shared with GtkSelection. */
49  static void selection_get_cb (GtkWidget *, GtkSelectionData *, guint,  GtkClipboard *cp_gtk_clipboard;
50                                guint, gpointer);  
51  static gint selection_clear_cb (GtkWidget *, GdkEventSelection *);  jstring cp_gtk_stringTarget;
52    jstring cp_gtk_imageTarget;
53  static GtkWidget *clipboard;  jstring cp_gtk_filesTarget;
54  static jobject cb_obj;  
55    /* Simple id to keep track of the selection we are currently managing. */
56  JNIEXPORT void JNICALL  static int current_selection = 0;
57  Java_gnu_java_awt_peer_gtk_GtkClipboard_initNativeState (JNIEnv *env,  
58                                                           jobject obj)  /* Whether we "own" the clipboard. And may clear it. */
59  {  static int owner = 0;
60    gdk_threads_enter ();  
61    static jclass gtk_clipboard_class;
62    if (!stringSelectionReceivedID)  static jmethodID setSystemContentsID;
63      {  
64        jclass gtkclipboard;  static jobject gtk_clipboard_instance = NULL;
65    static jmethodID provideContentID;
66        gtkclipboard = (*env)->FindClass (env,  static jmethodID provideTextID;
67                                          "gnu/java/awt/peer/gtk/GtkClipboard");  static jmethodID provideImageID;
68        stringSelectionReceivedID = (*env)->GetMethodID (env, gtkclipboard,  static jmethodID provideURIsID;
                                                     "stringSelectionReceived",  
                                                     "(Ljava/lang/String;)V");  
       stringSelectionHandlerID = (*env)->GetMethodID (env, gtkclipboard,  
                                                       "stringSelectionHandler",  
                                                       "()Ljava/lang/String;");  
       selectionClearID = (*env)->GetMethodID (env, gtkclipboard,  
                                               "selectionClear", "()V");  
     }  
   
   cb_obj = (*env)->NewGlobalRef (env, obj);  
69    
70    clipboard = gtk_window_new (GTK_WINDOW_TOPLEVEL);  /* Called when clipboard owner changes. Used to update available targets. */
71    #if GTK_MINOR_VERSION > 4
72    g_signal_connect (G_OBJECT(clipboard), "selection_received",  static void
73                      G_CALLBACK (selection_received_cb), NULL);  clipboard_owner_change_cb (GtkClipboard *clipboard __attribute__((unused)),
74                               GdkEvent *event __attribute__((unused)),
75    g_signal_connect (G_OBJECT(clipboard), "selection_clear_event",                             gpointer user_data __attribute__((unused)))
76                      G_CALLBACK (selection_clear_cb), NULL);  {
77      /* These are only interesting when we are not the owner. Otherwise
78    gtk_selection_add_target (clipboard, GDK_SELECTION_PRIMARY,       we will have the set and clear functions doing the updating. */
79                              GDK_TARGET_STRING, 0);    JNIEnv *env = cp_gtk_gdk_env ();
80      if (!owner)
81    g_signal_connect (G_OBJECT(clipboard), "selection_get",      (*env)->CallStaticVoidMethod (env, gtk_clipboard_class,
82                      G_CALLBACK (selection_get_cb), NULL);                                    setSystemContentsID);
   
   gdk_threads_leave ();  
83  }  }
84    #endif
85    
86  JNIEXPORT void JNICALL  JNIEXPORT jboolean JNICALL
87  Java_gnu_java_awt_peer_gtk_GtkClipboard_requestStringConversion  Java_gnu_java_awt_peer_gtk_GtkClipboard_initNativeState (JNIEnv *env,
88    (JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused)))                                                           jclass gtkclipboard,
89                                                             jstring string,
90                                                             jstring image,
91                                                             jstring files)
92  {  {
93    gdk_threads_enter ();    GdkDisplay* display;
94      jboolean can_cache;
95    
96    gtk_selection_convert (clipboard, GDK_SELECTION_PRIMARY,    gtk_clipboard_class = gtkclipboard;
97                           GDK_TARGET_STRING, GDK_CURRENT_TIME);    setSystemContentsID = (*env)->GetStaticMethodID (env, gtk_clipboard_class,
98                                                       "setSystemContents",
99                                                       "()V");
100      if (setSystemContentsID == NULL)
101        return JNI_FALSE;
102    
103      cp_gtk_stringTarget = (*env)->NewGlobalRef(env, string);
104      cp_gtk_imageTarget = (*env)->NewGlobalRef(env, image);
105      cp_gtk_filesTarget = (*env)->NewGlobalRef(env, files);
106    
107      gdk_threads_enter ();
108      cp_gtk_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
109    
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))
114        {
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;
120        }
121      else
122    #endif
123        can_cache = JNI_FALSE;
124    gdk_threads_leave ();    gdk_threads_leave ();
125    
126      return can_cache;
127  }  }
128    
129  static void  static void
130  selection_received_cb (GtkWidget *widget __attribute__((unused)),  clipboard_get_func (GtkClipboard *clipboard __attribute__((unused)),
131                         GtkSelectionData *selection_data __attribute__((unused)),                      GtkSelectionData *selection,
132                         guint time __attribute__((unused)),                      guint info,
133                         gpointer data __attribute__((unused)))                      gpointer user_data __attribute__((unused)))
134  {  {
135    /* Check to see if retrieval succeeded  */    JNIEnv *env = cp_gtk_gdk_env ();
136    if (selection_data->length < 0    
137        || selection_data->type != GDK_SELECTION_TYPE_STRING)    if (info == OBJECT_TARGET)
138      {      {
139        gdk_threads_leave ();        const gchar *target_name;
140          jstring target_string;
141          jbyteArray bytes;
142          jint len;
143          jbyte *barray;
144    
145          target_name = gdk_atom_name (selection->target);
146          if (target_name == NULL)
147            return;
148          target_string = (*env)->NewStringUTF (env, target_name);
149          if (target_string == NULL)
150            return;
151          bytes = (*env)->CallObjectMethod(env,
152                                           gtk_clipboard_instance,
153                                           provideContentID,
154                                           target_string);
155          if (bytes == NULL)
156            return;
157          len = (*env)->GetArrayLength(env, bytes);
158          if (len <= 0)
159            return;
160          barray = (*env)->GetByteArrayElements(env, bytes, NULL);
161          if (barray == NULL)
162            return;
163          gtk_selection_data_set (selection, selection->target, 8,
164                                  (guchar *) barray, len);
165    
166        (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), cb_obj, stringSelectionReceivedID,        (*env)->ReleaseByteArrayElements(env, bytes, barray, 0);
                                     NULL);  
167    
       gdk_threads_enter ();  
168      }      }
169    else    else if (info == TEXT_TARGET)
170      {      {
171        char *str = (char *) selection_data->data;        jstring string;
172                const gchar *text;
173        gdk_threads_leave ();        int len;
174          string = (*env)->CallObjectMethod(env,
175                                            gtk_clipboard_instance,
176                                            provideTextID);
177          if (string == NULL)
178            return;
179          len = (*env)->GetStringUTFLength (env, string);
180          if (len == -1)
181            return;
182          text = (*env)->GetStringUTFChars (env, string, NULL);
183          if (text == NULL)
184            return;
185    
186        (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), cb_obj, stringSelectionReceivedID,        gtk_selection_data_set_text (selection, text, len);
187                                      (*cp_gtk_gdk_env())->NewStringUTF (cp_gtk_gdk_env(), str));        (*env)->ReleaseStringUTFChars (env, string, text);
   
       gdk_threads_enter ();  
188      }      }
189      /* Images and URIs/Files support only available with gtk+2.6 or higher. */
190    return;  #if GTK_MINOR_VERSION > 4
191      else if (info == IMAGE_TARGET)
192        {
193          jobject gtkimage;
194          GdkPixbuf *pixbuf = NULL;
195          
196          gtkimage = (*env)->CallObjectMethod(env,
197                                              gtk_clipboard_instance,
198                                              provideImageID);
199          if (gtkimage == NULL)
200            return;
201          
202          pixbuf = cp_gtk_image_get_pixbuf (env, gtkimage);
203          if (pixbuf != NULL)
204            {
205              gtk_selection_data_set_pixbuf (selection, pixbuf);
206    
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);
211            }
212        }
213      else if (info == URI_TARGET)
214        {
215          jobjectArray uris;
216          jint count;
217          int i;
218          gchar **list;
219    
220          uris = (*env)->CallObjectMethod(env,
221                                          gtk_clipboard_instance,
222                                          provideURIsID);
223          if (uris == NULL)
224            return;
225          count = (*env)->GetArrayLength (env, uris);
226          if (count <= 0)
227            return;
228    
229          list = (gchar **) JCL_malloc (env, (count + 1) * sizeof (gchar *));
230          for (i = 0; i < count; i++)
231            {
232              const char *text;
233              jstring uri;
234              
235              /* Mark NULL in so case of some error we can find the end. */
236              list[i] = NULL;
237              uri = (*env)->GetObjectArrayElement (env, uris, i);
238              if (uri == NULL)
239                break;
240              text = (*env)->GetStringUTFChars (env, uri, NULL);
241              if (text == NULL)
242                break;
243              list[i] = strdup (text);
244              (*env)->ReleaseStringUTFChars (env, uri, text);
245            }
246    
247          if (i == count)
248            {
249              list[count] = NULL;
250              gtk_selection_data_set_uris (selection, list);
251            }
252    
253          for (i = 0; list[i] != NULL; i++)
254            free (list[i]);
255          JCL_free (env, list);
256        }
257    #endif
258  }  }
259    
260  static void  static void
261  selection_get_cb (GtkWidget *widget __attribute__((unused)),  clipboard_clear_func (GtkClipboard *clipboard __attribute__((unused)),
262                    GtkSelectionData *selection_data,                        gpointer user_data)
                   guint      info __attribute__((unused)),  
                   guint      time __attribute__((unused)),  
                   gpointer   data __attribute__((unused)))  
263  {  {
264    jstring jstr;    if (owner && (int) user_data == current_selection)
   const char *utf;  
   jsize utflen;  
   
   gdk_threads_leave ();  
   
   jstr = (*cp_gtk_gdk_env())->CallObjectMethod (cp_gtk_gdk_env(), cb_obj,  
                                        stringSelectionHandlerID);  
   
   gdk_threads_enter ();  
   
   if (!jstr)  
265      {      {
266        gtk_selection_data_set (selection_data,        JNIEnv *env = cp_gtk_gdk_env();
267                                GDK_TARGET_STRING, 8, NULL, 0);        owner = 0;
268        return;        (*env)->CallStaticVoidMethod (env, gtk_clipboard_class,
269                                        setSystemContentsID);
270      }      }
   
   utflen = (*cp_gtk_gdk_env())->GetStringUTFLength (cp_gtk_gdk_env(), jstr);  
   utf = (*cp_gtk_gdk_env())->GetStringUTFChars (cp_gtk_gdk_env(), jstr, NULL);  
   
   gtk_selection_data_set (selection_data, GDK_TARGET_STRING, 8,  
                           (const unsigned char*)utf, utflen);  
   
   (*cp_gtk_gdk_env())->ReleaseStringUTFChars (cp_gtk_gdk_env(), jstr, utf);  
271  }  }
272    
273  JNIEXPORT void JNICALL  JNIEXPORT void JNICALL
274  Java_gnu_java_awt_peer_gtk_GtkClipboard_selectionGet  Java_gnu_java_awt_peer_gtk_GtkClipboard_advertiseContent
275    (JNIEnv *env, jclass clazz __attribute__((unused)))  (JNIEnv *env,
276     jobject instance,
277     jobjectArray mime_array,
278    #if GTK_MINOR_VERSION > 4
279     jboolean add_text, jboolean add_images, jboolean add_uris)
280    #else
281     jboolean add_text __attribute__((unused)),
282     jboolean add_images __attribute__((unused)),
283     jboolean add_uris __attribute__((unused)))
284    #endif
285  {  {
286    GdkWindow *owner;    GtkTargetList *target_list;
287      GList *list;
288      GtkTargetEntry *targets;
289      gint n, i;
290    
291    gdk_threads_enter ();    gdk_threads_enter ();
292      target_list = gtk_target_list_new (NULL, 0);
293    
294    /* if we already own the clipboard, we need to tell the old data object    if (mime_array != NULL)
295       that we're no longer going to be using him */      {
296    owner = gdk_selection_owner_get (GDK_SELECTION_PRIMARY);        n = (*env)->GetArrayLength (env, mime_array);
297    if (owner && owner == clipboard->window)        for (i = 0; i < n; i++)
298      (*env)->CallVoidMethod (env, cb_obj, selectionClearID);          {
299                  const char *text;
300    gtk_selection_owner_set (clipboard, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);            jstring target;
301              GdkAtom atom;
302    
303              target = (*env)->GetObjectArrayElement (env, mime_array, i);
304              if (target == NULL)
305                break;
306              text = (*env)->GetStringUTFChars (env, target, NULL);
307              if (text == NULL)
308                break;
309    
310    gdk_threads_leave ();            atom = gdk_atom_intern (text, FALSE);
311  }            gtk_target_list_add (target_list, atom, 0, OBJECT_TARGET);
312    
313  static gint            (*env)->ReleaseStringUTFChars (env, target, text);
314  selection_clear_cb (GtkWidget *widget __attribute__((unused)),          }
315                      GdkEventSelection *event __attribute__((unused)))      }
 {  
   gdk_threads_leave ();  
   
   (*cp_gtk_gdk_env())->CallVoidMethod (cp_gtk_gdk_env(), cb_obj, selectionClearID);  
316    
317    gdk_threads_enter ();    /* Add extra targets that gtk+ can provide/translate for us. */
318    #if GTK_MINOR_VERSION > 4
319      if (add_text)
320        gtk_target_list_add_text_targets (target_list, TEXT_TARGET);
321      if (add_images)
322        gtk_target_list_add_image_targets (target_list, IMAGE_TARGET, TRUE);
323      if (add_uris)
324        gtk_target_list_add_uri_targets (target_list, URI_TARGET);
325    #else
326      if (add_text)
327        gtk_target_list_add (target_list,
328                             gdk_atom_intern ("STRING", FALSE),
329                             0, TEXT_TARGET);
330    #endif
331    
332    
333      /* Turn list into a target table. */
334      n = g_list_length (target_list->list);
335      if (n > 0)
336        {
337          targets = g_new (GtkTargetEntry, n);
338          for (list = target_list->list, i = 0;
339               list != NULL;
340               list = list->next, i++)
341            {
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;
346            }
347    
348          /* Set the targets plus callback functions and ask for the clipboard
349             to be stored when the application exists if supported. */
350          current_selection++;
351          if (gtk_clipboard_set_with_data (cp_gtk_clipboard, targets, n,
352                                           clipboard_get_func,
353                                           clipboard_clear_func,
354                                           (gpointer) current_selection))
355            {
356              owner = 1;
357              if (gtk_clipboard_instance == NULL)
358                {
359                  JNIEnv *env = cp_gtk_gdk_env ();
360                  gtk_clipboard_instance =  (*env)->NewGlobalRef(env, instance);
361    
362                  provideContentID
363                    = (*env)->GetMethodID (env, gtk_clipboard_class,
364                                           "provideContent",
365                                           "(Ljava/lang/String;)[B");
366                  if (provideContentID == NULL)
367                    return;
368    
369                  provideTextID
370                    = (*env)->GetMethodID (env, gtk_clipboard_class,
371                                           "provideText", "()Ljava/lang/String;");
372                  if (provideTextID == NULL)
373                    return;
374    
375                  provideImageID
376                    = (*env)->GetMethodID (env, gtk_clipboard_class,
377                                           "provideImage",
378                                           "()Lgnu/java/awt/peer/gtk/GtkImage;");
379                  if (provideImageID == NULL)
380                    return;
381    
382                  provideURIsID
383                    = (*env)->GetMethodID (env, gtk_clipboard_class,
384                                           "provideURIs",
385                                           "()[Ljava/lang/String;");
386                  if (provideURIsID == NULL)
387                    return;
388                }
389    #if GTK_MINOR_VERSION > 4
390              gtk_clipboard_set_can_store (cp_gtk_clipboard, NULL, 0);
391    #endif
392            }
393          else
394            {
395              owner = 0;
396              (*env)->CallStaticVoidMethod (env, gtk_clipboard_class,
397                                            setSystemContentsID);
398            }
399    
400          for (i = 0; i < n; i++)
401            g_free (targets[i].target);
402          g_free (targets);
403        }
404      else if (owner)
405        {
406          gtk_clipboard_clear (cp_gtk_clipboard);
407          owner = 0;
408        }
409    
410    return TRUE;    gtk_target_list_unref (target_list);
411      gdk_threads_leave ();
412  }  }

Legend:
Removed from v.1.7.2.3  
changed lines
  Added in v.1.7.2.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26