1 /*
2  * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 #ifdef HEADLESS
27     #error This file should not be included in headless library
28 #endif
29 
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <dlfcn.h>
34 
35 #include <jni.h>
36 #include <sizecalc.h>
37 #include "sun_awt_UNIXToolkit.h"
38 
39 #include "awt.h"
40 #include "gtk_interface.h"
41 
42 static jclass this_class = NULL;
43 static jmethodID icon_upcall_method = NULL;
44 
45 
46 /*
47  * Class:     sun_awt_UNIXToolkit
48  * Method:    check_gtk
49  * Signature: (I)Z
50  */
51 JNIEXPORT jboolean JNICALL
Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv * env,jclass klass,jint version)52 Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass, jint version) {
53     return (jboolean)gtk_check_version(version);
54 }
55 
56 
57 /*
58  * Class:     sun_awt_UNIXToolkit
59  * Method:    load_gtk
60  * Signature: (I)Z
61  */
62 JNIEXPORT jboolean JNICALL
Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv * env,jclass klass,jint version,jboolean verbose)63 Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass, jint version,
64                                                              jboolean verbose) {
65     return (jboolean)gtk_load(env, version, verbose);
66 }
67 
68 
69 /*
70  * Class:     sun_awt_UNIXToolkit
71  * Method:    unload_gtk
72  * Signature: ()Z
73  */
74 JNIEXPORT jboolean JNICALL
Java_sun_awt_UNIXToolkit_unload_1gtk(JNIEnv * env,jclass klass)75 Java_sun_awt_UNIXToolkit_unload_1gtk(JNIEnv *env, jclass klass)
76 {
77     return (jboolean)gtk->unload();
78 }
79 
init_method(JNIEnv * env,jobject this)80 jboolean init_method(JNIEnv *env, jobject this)
81 {
82     if (this_class == NULL) {
83         this_class = (*env)->NewGlobalRef(env,
84                                           (*env)->GetObjectClass(env, this));
85         icon_upcall_method = (*env)->GetMethodID(env, this_class,
86                                  "loadIconCallback", "([BIIIIIZ)V");
87         CHECK_NULL_RETURN(icon_upcall_method, JNI_FALSE);
88     }
89     return JNI_TRUE;
90 }
91 
92 /*
93  * Class:     sun_awt_UNIXToolkit
94  * Method:    load_gtk_icon
95  * Signature: (Ljava/lang/String)Z
96  *
97  * This method assumes that GTK libs are present.
98  */
99 JNIEXPORT jboolean JNICALL
Java_sun_awt_UNIXToolkit_load_1gtk_1icon(JNIEnv * env,jobject this,jstring filename)100 Java_sun_awt_UNIXToolkit_load_1gtk_1icon(JNIEnv *env, jobject this,
101         jstring filename)
102 {
103     int len;
104     jsize jlen;
105     char *filename_str = NULL;
106     GError **error = NULL;
107 
108     if (filename == NULL)
109     {
110         return JNI_FALSE;
111     }
112 
113     len = (*env)->GetStringUTFLength(env, filename);
114     jlen = (*env)->GetStringLength(env, filename);
115     filename_str = (char *)SAFE_SIZE_ARRAY_ALLOC(malloc,
116             sizeof(char), len + 1);
117     if (filename_str == NULL) {
118         JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
119         return JNI_FALSE;
120     }
121     if (!init_method(env, this) ) {
122         free(filename_str);
123         return JNI_FALSE;
124     }
125     (*env)->GetStringUTFRegion(env, filename, 0, jlen, filename_str);
126     jboolean result = gtk->get_file_icon_data(env, filename_str, error,
127                                             icon_upcall_method, this);
128 
129     /* Release the strings we've allocated. */
130     free(filename_str);
131 
132     return result;
133 }
134 
135 /*
136  * Class:     sun_awt_UNIXToolkit
137  * Method:    load_stock_icon
138  * Signature: (ILjava/lang/String;IILjava/lang/String;)Z
139  *
140  * This method assumes that GTK libs are present.
141  */
142 JNIEXPORT jboolean JNICALL
Java_sun_awt_UNIXToolkit_load_1stock_1icon(JNIEnv * env,jobject this,jint widget_type,jstring stock_id,jint icon_size,jint text_direction,jstring detail)143 Java_sun_awt_UNIXToolkit_load_1stock_1icon(JNIEnv *env, jobject this,
144         jint widget_type, jstring stock_id, jint icon_size,
145         jint text_direction, jstring detail)
146 {
147     int len;
148     jsize jlen;
149     char *stock_id_str = NULL;
150     char *detail_str = NULL;
151     jboolean result = JNI_FALSE;
152 
153     if (stock_id == NULL)
154     {
155         return JNI_FALSE;
156     }
157 
158     len = (*env)->GetStringUTFLength(env, stock_id);
159     jlen = (*env)->GetStringLength(env, stock_id);
160     stock_id_str = (char *)SAFE_SIZE_ARRAY_ALLOC(malloc,
161             sizeof(char), len + 1);
162     if (stock_id_str == NULL) {
163         JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
164         return JNI_FALSE;
165     }
166     (*env)->GetStringUTFRegion(env, stock_id, 0, jlen, stock_id_str);
167 
168     /* Detail isn't required so check for NULL. */
169     if (detail != NULL)
170     {
171         len = (*env)->GetStringUTFLength(env, detail);
172         jlen = (*env)->GetStringLength(env, detail);
173         detail_str = (char *)SAFE_SIZE_ARRAY_ALLOC(malloc,
174                 sizeof(char), len + 1);
175         if (detail_str == NULL) {
176             free(stock_id_str);
177             JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
178             return JNI_FALSE;
179         }
180         (*env)->GetStringUTFRegion(env, detail, 0, jlen, detail_str);
181     }
182 
183     if (init_method(env, this)) {
184         result = gtk->get_icon_data(env, widget_type, stock_id_str,
185                                     icon_size, text_direction, detail_str,
186                                     icon_upcall_method, this);
187     }
188     /* Release the strings we've allocated. */
189     free(stock_id_str);
190     free(detail_str);
191 
192     return result;
193 }
194 
195 /*
196  * Class:     sun_awt_UNIXToolkit
197  * Method:    nativeSync
198  * Signature: ()V
199  */
200 JNIEXPORT void JNICALL
Java_sun_awt_UNIXToolkit_nativeSync(JNIEnv * env,jobject this)201 Java_sun_awt_UNIXToolkit_nativeSync(JNIEnv *env, jobject this)
202 {
203     AWT_LOCK();
204     XSync(awt_display, False);
205     AWT_UNLOCK();
206 }
207 
208 /*
209  * Class:     sun_awt_SunToolkit
210  * Method:    closeSplashScreen
211  * Signature: ()V
212  */
213 JNIEXPORT void JNICALL
Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv * env,jclass cls)214 Java_sun_awt_SunToolkit_closeSplashScreen(JNIEnv *env, jclass cls)
215 {
216     typedef void (*SplashClose_t)();
217     SplashClose_t splashClose;
218     void* hSplashLib = dlopen(0, RTLD_LAZY);
219     if (!hSplashLib) {
220         return;
221     }
222     splashClose = (SplashClose_t)dlsym(hSplashLib,
223         "SplashClose");
224     if (splashClose) {
225         splashClose();
226     }
227     dlclose(hSplashLib);
228 }
229 
230 /*
231  * Class:     sun_awt_UNIXToolkit
232  * Method:    gtkCheckVersionImpl
233  * Signature: (III)Ljava/lang/String;
234  */
235 JNIEXPORT jboolean JNICALL
Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl(JNIEnv * env,jobject this,jint major,jint minor,jint micro)236 Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl(JNIEnv *env, jobject this,
237         jint major, jint minor, jint micro)
238 {
239     char *ret;
240 
241     ret = gtk->gtk_check_version(major, minor, micro);
242     if (ret == NULL) {
243         return TRUE;
244     }
245 
246     return FALSE;
247 }
248 
249 /*
250  * Class:     sun_awt_UNIXToolkit
251  * Method:    get_gtk_version
252  * Signature: ()I
253  */
254 JNIEXPORT jint JNICALL
Java_sun_awt_UNIXToolkit_get_1gtk_1version(JNIEnv * env,jclass klass)255 Java_sun_awt_UNIXToolkit_get_1gtk_1version(JNIEnv *env, jclass klass)
256 {
257     return gtk ? gtk->version : GTK_ANY;
258 }
259