1 /* gtkpeer.c -- Some GTK peer specific helper functions
2    Copyright (C) 2007 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 #include "gtkpeer.h"
39 #include "jni.h"
40 
41 /**
42  * The Pointer class.
43  */
44 static jclass pointerClass;
45 
46 /**
47  * The Pointer constructor.
48  */
49 static jmethodID pointerConstructorMID;
50 
51 /**
52  * The field ID of the data field in the Pointer class.
53  */
54 static jfieldID pointerDataFID;
55 
56 /**
57  * The field ID of the widget field in the GtkGenericPeer class.
58  */
59 static jfieldID widgetFID;
60 
61 /**
62  * The field ID of the globalRef field in the GtkGenericPeer class.
63  */
64 static jfieldID globalRefFID;
65 
66 /**
67  * The field ID of the display field in the GdkGraphicsEnvironment class.
68  */
69 static jfieldID displayFID;
70 
71 /**
72  * The field ID of the screen field in the GdkScreenGraphicsDevice class.
73  */
74 static jfieldID screenFID;
75 
76 /**
77  * The field ID of the nativeFont field in GdkFontPeer.
78  */
79 static jfieldID fontFID;
80 
81 /**
82  * The field ID of the nativeDecoder field in GdkPixbufDecoder.
83  */
84 static jfieldID pixbufLoaderFID;
85 
86 /**
87  * Initializes the IDs of the Pointer* classes.
88  *
89  * @param env the JNI environment
90  */
gtkpeer_init_pointer_IDs(JNIEnv * env)91 void gtkpeer_init_pointer_IDs(JNIEnv* env)
92 {
93 #if SIZEOF_VOID_P == 8
94   pointerClass = (*env)->FindClass (env, "gnu/classpath/Pointer64");
95   if (pointerClass != NULL)
96     {
97       pointerClass = (*env)->NewGlobalRef (env, pointerClass);
98       pointerDataFID = (*env)->GetFieldID (env, pointerClass, "data", "J");
99       pointerConstructorMID = (*env)->GetMethodID (env, pointerClass, "<init>",
100 						   "(J)V");
101     }
102 #else
103 #if SIZEOF_VOID_P == 4
104   pointerClass = (*env)->FindClass(env, "gnu/classpath/Pointer32");
105   if (pointerClass != NULL)
106     {
107       pointerClass = (*env)->NewGlobalRef (env, pointerClass);
108       pointerDataFID = (*env)->GetFieldID (env, pointerClass, "data", "I");
109       pointerConstructorMID = (*env)->GetMethodID (env, pointerClass, "<init>",
110                                                    "(I)V");
111     }
112 #else
113 #error "Pointer size is not supported."
114 #endif /* SIZEOF_VOID_P == 4 */
115 #endif /* SIZEOF_VOID_P == 8 */
116 }
117 
118 /**
119  * Initializes the field IDs for the widget reference.
120  *
121  * @param env the JNI environment
122  */
gtkpeer_init_widget_IDs(JNIEnv * env)123 void gtkpeer_init_widget_IDs(JNIEnv *env)
124 {
125   jclass cls;
126 
127   /* Find the widget field ID in GtkGenericPeer. */
128   cls = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GtkGenericPeer");
129   widgetFID = (*env)->GetFieldID(env, cls, "widget",
130                                  "Lgnu/classpath/Pointer;");
131 
132   /* Find the globalRef field in GtkGenericPeer. */
133   globalRefFID = (*env)->GetFieldID(env, cls, "globalRef",
134                                  "Lgnu/classpath/Pointer;");
135 }
136 
137 /**
138  * Stores the GTK widget reference in the GtkGenericPeer object.
139  *
140  * @param env the JNI environment
141  * @param peer the actual peer object
142  * @param widget the widget reference to store
143  */
gtkpeer_set_widget(JNIEnv * env,jobject peer,void * widget)144 void gtkpeer_set_widget(JNIEnv *env, jobject peer, void *widget)
145 {
146   jobject obj;
147 
148   /* Fetch the widget field object. */
149   obj = (*env)->GetObjectField(env, peer, widgetFID);
150   if (obj == NULL)
151     {
152       /* Create if necessary. */
153 #if SIZEOF_VOID_P == 8
154       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
155                               (jlong) widget);
156 #else
157       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
158                               (jint) widget);
159 #endif
160       (*env)->SetObjectField(env, peer, widgetFID, obj);
161     }
162   else
163     {
164 #if SIZEOF_VOID_P == 8
165       (*env)->SetLongField(env, obj, pointerDataFID, (jlong) widget);
166 #else
167       (*env)->SetIntField(env, obj, pointerDataFID, (jint) widget);
168 #endif
169     }
170 }
171 
172 /**
173  * Retrieves the GTK widget reference from a GtkGenericPeer object.
174  *
175  * @param env the JNI environment
176  * @param peer the actual peer object
177  *
178  * @return the widget reference
179  */
gtkpeer_get_widget(JNIEnv * env,jobject peer)180 void* gtkpeer_get_widget(JNIEnv *env, jobject peer)
181 {
182   jobject obj;
183   void *widget;
184 
185   /* Fetch the widget field from the peer object. */
186   obj = (*env)->GetObjectField(env, peer, widgetFID);
187 
188   /* Fetch actual widget pointer. */
189 #if SIZEOF_VOID_P == 8
190   widget = (void*) (*env)->GetLongField(env, obj, pointerDataFID);
191 #else
192   widget = (void*) (*env)->GetIntField(env, obj, pointerDataFID);
193 #endif
194   return widget;
195 }
196 
197 
198 /**
199  * Stores the global JNI reference of a peer inside the peer.
200  *
201  * @param env the JNI environment
202  * @param peer the peer object
203  */
gtkpeer_set_global_ref(JNIEnv * env,jobject peer)204 void gtkpeer_set_global_ref(JNIEnv *env, jobject peer)
205 {
206   jobject obj;
207   void* globalRef;
208 
209   /* Create global reference. */
210   globalRef = (*env)->NewGlobalRef(env, peer);
211 
212   /* Fetch the globalRef field object. */
213   obj = (*env)->GetObjectField(env, peer, globalRefFID);
214   if (obj == NULL)
215     {
216       /* Create if necessary. */
217 #if SIZEOF_VOID_P == 8
218       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
219                               (jlong) globalRef);
220 #else
221       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
222                               (jint) globalRef);
223 #endif
224       (*env)->SetObjectField(env, peer, globalRefFID, obj);
225     }
226   else
227     {
228 #if SIZEOF_VOID_P == 8
229       (*env)->SetLongField(env, obj, pointerDataFID, (jlong) globalRef);
230 #else
231       (*env)->SetIntField(env, obj, pointerDataFID, (jint) globalRef);
232 #endif
233     }
234 }
235 
236 /**
237  * Retrieves the global reference from a peer.
238  *
239  * @param env the JNI environment
240  * @param peer the peer object
241  *
242  * @return the global reference
243  */
gtkpeer_get_global_ref(JNIEnv * env,jobject peer)244 void* gtkpeer_get_global_ref(JNIEnv *env, jobject peer)
245 {
246   jobject obj;
247   void *globalRef;
248 
249   /* Fetch the globalRef field from the peer object. */
250   obj = (*env)->GetObjectField(env, peer, globalRefFID);
251 
252   /* Fetch actual globalRef pointer. */
253 #if SIZEOF_VOID_P == 8
254   globalRef = (void*) (*env)->GetLongField(env, obj, pointerDataFID);
255 #else
256   globalRef = (void*) (*env)->GetIntField(env, obj, pointerDataFID);
257 #endif
258   return globalRef;
259 }
260 
261 /**
262  * Deletes the global reference of a peer. This is necessary in order to
263  * allow the peer to be garbage collected.
264  *
265  * @param env the JNI environment
266  * @param peer the peer object.
267  */
gtkpeer_del_global_ref(JNIEnv * env,jobject peer)268 void gtkpeer_del_global_ref(JNIEnv* env, jobject peer)
269 {
270   jobject obj;
271   void *globalRef;
272 
273   /* Fetch the globalRef field from the peer object. */
274   obj = (*env)->GetObjectField(env, peer, globalRefFID);
275 
276   /* Fetch actual globalRef pointer. */
277 #if SIZEOF_VOID_P == 8
278   globalRef = (void*) (*env)->GetLongField(env, obj, pointerDataFID);
279 #else
280   globalRef = (void*) (*env)->GetIntField(env, obj, pointerDataFID);
281 #endif
282   (*env)->DeleteGlobalRef(env, globalRef);
283 }
284 
285 /**
286  * Initializes the fieldIDs for the display and screen fields.
287  *
288  * @param env the JNI environment
289  */
gtkpeer_init_display_IDs(JNIEnv * env)290 void gtkpeer_init_display_IDs(JNIEnv* env)
291 {
292   jclass cls;
293 
294   /* Find the display field ID in GdkGraphicsEnvironment. */
295   cls = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GdkGraphicsEnvironment");
296   displayFID = (*env)->GetFieldID(env, cls, "display",
297                                   "Lgnu/classpath/Pointer;");
298 }
299 
300 /**
301  * Sets the native display pointer in the GdkGraphicsEnvironment object.
302  *
303  * @param env the JNI environment
304  * @param graphicsenv the GdkGraphicsEnvironment object
305  * @param display the native display pointer
306  */
gtkpeer_set_display(JNIEnv * env,jobject graphicsenv,void * display)307 void gtkpeer_set_display(JNIEnv* env, jobject graphicsenv, void* display)
308 {
309   jobject obj;
310 
311   /* Fetch the display field object. */
312   obj = (*env)->GetObjectField(env, graphicsenv, displayFID);
313   if (obj == NULL)
314     {
315       /* Create if necessary. */
316 #if SIZEOF_VOID_P == 8
317       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
318                               (jlong) display);
319 #else
320       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
321                               (jint) display);
322 #endif
323       (*env)->SetObjectField(env, graphicsenv, displayFID, obj);
324     }
325   else
326     {
327 #if SIZEOF_VOID_P == 8
328       (*env)->SetLongField(env, obj, pointerDataFID, (jlong) display);
329 #else
330       (*env)->SetIntField(env, obj, pointerDataFID, (jint) display);
331 #endif
332     }
333 }
334 
335 /**
336  * Fetches the native display pointer from the GdkGraphicsEnvironment object.
337  *
338  * @param env the JNI environment
339  * @param graphicsenv the GdkGraphicsEnvironment object
340  *
341  * @return the native display pointer
342  */
gtkpeer_get_display(JNIEnv * env,jobject graphicsenv)343 void* gtkpeer_get_display(JNIEnv* env, jobject graphicsenv)
344 {
345   jobject obj;
346   void *display;
347 
348   /* Fetch the display field from the peer object. */
349   obj = (*env)->GetObjectField(env, graphicsenv, displayFID);
350 
351   /* Fetch actual display pointer. */
352 #if SIZEOF_VOID_P == 8
353   display = (void*) (*env)->GetLongField(env, obj, pointerDataFID);
354 #else
355   display = (void*) (*env)->GetIntField(env, obj, pointerDataFID);
356 #endif
357   return display;
358 }
359 
360 /**
361  * Initializes the fieldIDs for the screen field.
362  *
363  * @param env the JNI environment
364  */
gtkpeer_init_screen_IDs(JNIEnv * env)365 void gtkpeer_init_screen_IDs(JNIEnv* env)
366 {
367   jclass cls;
368 
369   /* Find the display field ID in GdkScreenGraphicsDevice. */
370   cls = (*env)->FindClass(env,
371                           "gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice");
372   screenFID = (*env)->GetFieldID(env, cls, "screen",
373                                  "Lgnu/classpath/Pointer;");
374 }
375 
376 /**
377  * Sets the native screen in the GdkScreenGraphicsDevice object.
378  *
379  * @param env the JNI environment
380  * @param screen_graphics_device the GdkScreenGraphicsDevice object
381  * @param ptr the native screen pointer
382  */
gtkpeer_set_screen(JNIEnv * env,jobject screen_graphics_device,void * ptr)383 void gtkpeer_set_screen(JNIEnv* env, jobject screen_graphics_device,
384                         void* ptr)
385 {
386   jobject obj;
387 
388   /* Fetch the screen field object. */
389   obj = (*env)->GetObjectField(env, screen_graphics_device, screenFID);
390   if (obj == NULL)
391     {
392       /* Create if necessary. */
393 #if SIZEOF_VOID_P == 8
394       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
395                               (jlong) ptr);
396 #else
397       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
398                               (jint) ptr);
399 #endif
400       (*env)->SetObjectField(env, screen_graphics_device, screenFID, obj);
401     }
402   else
403     {
404 #if SIZEOF_VOID_P == 8
405       (*env)->SetLongField(env, obj, pointerDataFID, (jlong) ptr);
406 #else
407       (*env)->SetIntField(env, obj, pointerDataFID, (jint) ptr);
408 #endif
409     }
410 }
411 
412 /**
413  * Fetches the native screen pointer from the GdkScreenGraphicsDevice object.
414  *
415  * @param env the JNI environment
416  * @param screen_graphics_device the GdkScreenGraphicsDevice object
417  *
418  * @return the native screen pointer
419  */
gtkpeer_get_screen(JNIEnv * env,jobject screen_graphics_device)420 void* gtkpeer_get_screen(JNIEnv* env, jobject screen_graphics_device)
421 {
422   jobject obj;
423   void *screen;
424 
425   /* Fetch the display field from the peer object. */
426   obj = (*env)->GetObjectField(env, screen_graphics_device, screenFID);
427 
428   /* Fetch actual display pointer. */
429 #if SIZEOF_VOID_P == 8
430   screen = (void*) (*env)->GetLongField(env, obj, pointerDataFID);
431 #else
432   screen = (void*) (*env)->GetIntField(env, obj, pointerDataFID);
433 #endif
434   return screen;
435 }
436 
437 /**
438  * Initializes the field IDs for fonts.
439  *
440  * @param env the JNI environment
441  */
gtkpeer_init_font_IDs(JNIEnv * env)442 void gtkpeer_init_font_IDs(JNIEnv* env)
443 {
444   jclass cls;
445 
446   /* Find the nativeFont field ID in GdkFontPeer. */
447   cls = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GdkFontPeer");
448   fontFID = (*env)->GetFieldID(env, cls, "nativeFont",
449                                "Lgnu/classpath/Pointer;");
450 }
451 
452 /**
453  * Sets the native font in the nativeFont field in GdkFontPeer.
454  *
455  * @param env the JNI environment
456  * @param font_peer the font peer object
457  * @param font the actual native font reference
458  */
gtkpeer_set_font(JNIEnv * env,jobject font_peer,void * font)459 void gtkpeer_set_font(JNIEnv* env, jobject font_peer, void* font)
460 {
461   jobject obj;
462 
463   /* Fetch the nativeFont field object. */
464   obj = (*env)->GetObjectField(env, font_peer, fontFID);
465   if (obj == NULL)
466     {
467       /* Create if necessary. */
468 #if SIZEOF_VOID_P == 8
469       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
470                               (jlong) font);
471 #else
472       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
473                               (jint) font);
474 #endif
475       (*env)->SetObjectField(env, font_peer, fontFID, obj);
476     }
477   else
478     {
479 #if SIZEOF_VOID_P == 8
480       (*env)->SetLongField(env, obj, pointerDataFID, (jlong) font);
481 #else
482       (*env)->SetIntField(env, obj, pointerDataFID, (jint) font);
483 #endif
484     }
485 }
486 
487 /**
488  * Fetches the native font reference from the GdkFontPeer object.
489  *
490  * @param env the JNI environment
491  * @param font_peer the font peer object
492  *
493  * @return the native font structure
494  */
gtkpeer_get_font(JNIEnv * env,jobject font_peer)495 void* gtkpeer_get_font(JNIEnv* env, jobject font_peer)
496 {
497   jobject obj;
498   void *font;
499 
500   /* Fetch the nativeFont field from the peer object. */
501   obj = (*env)->GetObjectField(env, font_peer, fontFID);
502 
503   /* Fetch actual font pointer. */
504 #if SIZEOF_VOID_P == 8
505   font = (void*) (*env)->GetLongField(env, obj, pointerDataFID);
506 #else
507   font = (void*) (*env)->GetIntField(env, obj, pointerDataFID);
508 #endif
509   return font;
510 }
511 
512 /**
513  * Initializes the field IDs for pixbuf decoder.
514  *
515  * @param env the JNI environment
516  */
gtkpeer_init_pixbuf_IDs(JNIEnv * env)517 void gtkpeer_init_pixbuf_IDs(JNIEnv* env)
518 {
519   jclass cls;
520 
521   /* Find the nativeFont field ID in GdkFontPeer. */
522   cls = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder");
523   pixbufLoaderFID = (*env)->GetFieldID(env, cls, "nativeDecoder",
524                                        "Lgnu/classpath/Pointer;");
525 }
526 
527 /**
528  * Sets the native font in the nativeFont field in GdkFontPeer.
529  *
530  * @param env the JNI environment
531  * @param pixbuf_dec the pixbuf decoder object
532  * @param pixbuf_loader the native pixbuf loader
533  */
gtkpeer_set_pixbuf_loader(JNIEnv * env,jobject pixbuf_dec,void * pixbuf_loader)534 void gtkpeer_set_pixbuf_loader(JNIEnv* env, jobject pixbuf_dec,
535                                void* pixbuf_loader)
536 {
537   jobject obj;
538 
539   /* Fetch the nativeDecoder field object. */
540   obj = (*env)->GetObjectField(env, pixbuf_dec, pixbufLoaderFID);
541   if (obj == NULL)
542     {
543       /* Create if necessary. */
544 #if SIZEOF_VOID_P == 8
545       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
546                               (jlong) pixbuf_loader);
547 #else
548       obj = (*env)->NewObject(env, pointerClass, pointerConstructorMID,
549                               (jint) pixbuf_loader);
550 #endif
551       (*env)->SetObjectField(env, pixbuf_dec, pixbufLoaderFID, obj);
552     }
553   else
554     {
555 #if SIZEOF_VOID_P == 8
556       (*env)->SetLongField(env, obj, pointerDataFID, (jlong) pixbuf_loader);
557 #else
558       (*env)->SetIntField(env, obj, pointerDataFID, (jint) pixbuf_loader);
559 #endif
560     }
561 }
562 
563 /**
564  * Fetches the native pixbuf loader reference from the GdkPixbufDecoder object.
565  *
566  * @param env the JNI environment
567  * @param pixbuf_dec the pixbuf decoder object
568  *
569  * @return the native pixbuf loader
570  */
gtkpeer_get_pixbuf_loader(JNIEnv * env,jobject pixbuf_dec)571 void* gtkpeer_get_pixbuf_loader(JNIEnv* env, jobject pixbuf_dec)
572 {
573   jobject obj;
574   void *loader;
575 
576   /* Fetch the nativeFont field from the peer object. */
577   obj = (*env)->GetObjectField(env, pixbuf_dec, pixbufLoaderFID);
578 
579   /* Fetch actual font pointer. */
580 #if SIZEOF_VOID_P == 8
581   loader = (void*) (*env)->GetLongField(env, obj, pointerDataFID);
582 #else
583   loader = (void*) (*env)->GetIntField(env, obj, pointerDataFID);
584 #endif
585   return loader;
586 }
587