Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkToolkit.c
blobb14330e5fe225a986d1834bf66e9e3edbfbea5f2
1 /* gtktoolkit.c -- Native portion of GtkToolkit
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)
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 "gtkpeer.h"
40 #include "gnu_java_awt_peer_gtk_GtkToolkit.h"
41 #include "gthread-jni.h"
42 #include "jcl.h"
43 #include <gdk/gdkx.h>
45 #define RC_FILE ".classpath-gtkrc"
47 /* From java.awt.SystemColor */
48 #define AWT_DESKTOP 0
49 #define AWT_ACTIVE_CAPTION 1
50 #define AWT_ACTIVE_CAPTION_TEXT 2
51 #define AWT_ACTIVE_CAPTION_BORDER 3
52 #define AWT_INACTIVE_CAPTION 4
53 #define AWT_INACTIVE_CAPTION_TEXT 5
54 #define AWT_INACTIVE_CAPTION_BORDER 6
55 #define AWT_WINDOW 7
56 #define AWT_WINDOW_BORDER 8
57 #define AWT_WINDOW_TEXT 9
58 #define AWT_MENU 10
59 #define AWT_MENU_TEXT 11
60 #define AWT_TEXT 12
61 #define AWT_TEXT_TEXT 13
62 #define AWT_TEXT_HIGHLIGHT 14
63 #define AWT_TEXT_HIGHLIGHT_TEXT 15
64 #define AWT_TEXT_INACTIVE_TEXT 16
65 #define AWT_CONTROL 17
66 #define AWT_CONTROL_TEXT 18
67 #define AWT_CONTROL_HIGHLIGHT 19
68 #define AWT_CONTROL_LT_HIGHLIGHT 20
69 #define AWT_CONTROL_SHADOW 21
70 #define AWT_CONTROL_DK_SHADOW 22
71 #define AWT_SCROLLBAR 23
72 #define AWT_INFO 24
73 #define AWT_INFO_TEXT 25
74 #define AWT_NUM_COLORS 26
76 struct state_table *cp_gtk_native_state_table;
77 struct state_table *cp_gtk_native_global_ref_table;
79 static jclass gtkgenericpeer;
80 static JavaVM *java_vm;
81 static jmethodID printCurrentThreadID;
83 union env_union
85 void *void_env;
86 JNIEnv *jni_env;
89 JNIEnv *
90 cp_gtk_gdk_env()
92 union env_union tmp;
93 g_assert((*java_vm)->GetEnv(java_vm, &tmp.void_env, JNI_VERSION_1_2) == JNI_OK);
94 return tmp.jni_env;
98 GtkWindowGroup *cp_gtk_global_window_group;
99 double cp_gtk_dpi_conversion_factor;
101 static void init_glib_threads(JNIEnv *, jint);
103 static void init_dpi_conversion_factor (void);
104 static void dpi_changed_cb (GtkSettings *settings,
105 GParamSpec *pspec);
107 #if GTK_MINOR_VERSION > 4
108 static GLogFunc old_glog_func;
109 static void glog_func (const gchar *log_domain,
110 GLogLevelFlags log_level,
111 const gchar *message,
112 gpointer user_data);
113 #endif
116 * Call gtk_init. It is very important that this happen before any other
117 * gtk calls.
119 * The portableNativeSync argument may have the values:
120 * 1 if the Java property gnu.classpath.awt.gtk.portable.native.sync
121 * is set to "true".
122 * 0 if it is set to "false"
123 * -1 if unset.
127 JNIEXPORT void JNICALL
128 Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkInit (JNIEnv *env,
129 jclass clazz __attribute__((unused)),
130 jint portableNativeSync)
132 int argc = 1;
133 char **argv;
134 char *homedir, *rcpath = NULL;
136 gtkgenericpeer = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GtkGenericPeer");
138 gtkgenericpeer = (*env)->NewGlobalRef(env, gtkgenericpeer);
140 printCurrentThreadID = (*env)->GetStaticMethodID (env, gtkgenericpeer,
141 "printCurrentThread", "()V");
143 NSA_INIT (env, gtkgenericpeer);
145 g_assert((*env)->GetJavaVM(env, &java_vm) == 0);
147 /* GTK requires a program's argc and argv variables, and requires that they
148 be valid. Set it up. */
149 argv = (char **) g_malloc (sizeof (char *) * 2);
150 argv[0] = (char *) g_malloc(1);
151 argv[0][0] = '\0';
152 argv[1] = NULL;
154 init_glib_threads(env, portableNativeSync);
156 /* From GDK 2.0 onwards we have to explicitly call gdk_threads_init */
157 gdk_threads_init();
159 gtk_init (&argc, &argv);
161 #if SYNCHRONIZE_GDK
162 XSynchronize (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), True);
163 #endif
165 gtk_widget_set_default_colormap (gdk_rgb_get_colormap ());
167 /* Make sure queued calls don't get sent to GTK/GDK while
168 we're shutting down. */
169 atexit (gdk_threads_enter);
171 if ((homedir = getenv ("HOME")))
173 rcpath = (char *) g_malloc (strlen (homedir) + strlen (RC_FILE) + 2);
174 sprintf (rcpath, "%s/%s", homedir, RC_FILE);
177 gtk_rc_parse ((rcpath) ? rcpath : RC_FILE);
179 g_free (rcpath);
180 g_free (argv[0]);
181 g_free (argv);
183 /* On errors or warning print a whole stacktrace. */
184 #if GTK_MINOR_VERSION > 4
185 old_glog_func = g_log_set_default_handler (&glog_func, NULL);
186 #endif
188 #if GTK_CAIRO
189 cp_gtk_graphics2d_init_jni ();
190 #endif
191 cp_gtk_graphics_init_jni ();
192 cp_gtk_button_init_jni ();
193 cp_gtk_checkbox_init_jni ();
194 cp_gtk_choice_init_jni ();
195 cp_gtk_component_init_jni ();
196 cp_gtk_filedialog_init_jni ();
197 cp_gtk_list_init_jni ();
198 cp_gtk_menuitem_init_jni ();
199 cp_gtk_scrollbar_init_jni ();
200 cp_gtk_textcomponent_init_jni ();
201 cp_gtk_window_init_jni ();
203 cp_gtk_global_window_group = gtk_window_group_new ();
205 init_dpi_conversion_factor ();
209 /** Initialize GLIB's threads properly, based on the value of the
210 gnu.classpath.awt.gtk.portable.native.sync Java system property. If
211 that's unset, use the PORTABLE_NATIVE_SYNC config.h macro. (TODO:
212 In some release following 0.10, that config.h macro will go away.)
214 static void
215 init_glib_threads(JNIEnv *env, jint portableNativeSync)
217 if (portableNativeSync < 0)
219 #ifdef PORTABLE_NATIVE_SYNC /* Default value, if not set by the Java system
220 property */
221 portableNativeSync = 1;
222 #else
223 portableNativeSync = 0;
224 #endif
227 (*env)->GetJavaVM( env, &cp_gtk_the_vm );
228 if (!g_thread_supported ())
230 if (portableNativeSync)
231 g_thread_init ( &cp_gtk_portable_native_sync_jni_functions );
232 else
233 g_thread_init ( NULL );
235 else
237 /* Warn if portable native sync is desired but the threading
238 system is already initialized. In that case we can't
239 override the threading implementation with our portable
240 native sync functions. */
241 if (portableNativeSync)
242 g_printerr ("peer warning: portable native sync disabled.\n");
245 /* Debugging progress message; uncomment if needed: */
246 /* printf("called gthread init\n"); */
249 void
250 cp_gtk_print_current_thread (void)
252 (*cp_gtk_gdk_env())->CallStaticVoidMethod (cp_gtk_gdk_env(), gtkgenericpeer, printCurrentThreadID);
255 /* This is a big hack, needed until this pango bug is resolved:
256 http://bugzilla.gnome.org/show_bug.cgi?id=119081.
257 See: http://mail.gnome.org/archives/gtk-i18n-list/2003-August/msg00001.html
258 for details. */
259 static void
260 init_dpi_conversion_factor ()
262 GtkSettings *settings = gtk_settings_get_default ();
263 GObjectClass *klass;
265 klass = G_OBJECT_CLASS (GTK_SETTINGS_GET_CLASS (settings));
266 if (g_object_class_find_property (klass, "gtk-xft-dpi"))
268 int int_dpi;
269 g_object_get (settings, "gtk-xft-dpi", &int_dpi, NULL);
270 /* If int_dpi == -1 gtk-xft-dpi returns the default value. So we
271 have to do approximate calculation here. */
272 if (int_dpi < 0)
273 cp_gtk_dpi_conversion_factor = PANGO_SCALE * 72.0 / 96.;
274 else
275 cp_gtk_dpi_conversion_factor =
276 PANGO_SCALE * 72.0 / (int_dpi / PANGO_SCALE);
278 g_signal_connect (settings, "notify::gtk-xft-dpi",
279 G_CALLBACK (dpi_changed_cb), NULL);
281 else
282 /* Approximate. */
283 cp_gtk_dpi_conversion_factor = PANGO_SCALE * 72.0 / 96.;
286 static void
287 dpi_changed_cb (GtkSettings *settings,
288 GParamSpec *pspec __attribute__((unused)))
290 int int_dpi;
291 g_object_get (settings, "gtk-xft-dpi", &int_dpi, NULL);
292 if (int_dpi < 0)
293 cp_gtk_dpi_conversion_factor = PANGO_SCALE * 72.0 / 96.;
294 else
295 cp_gtk_dpi_conversion_factor =
296 PANGO_SCALE * 72.0 / (int_dpi / PANGO_SCALE);
299 #if GTK_MINOR_VERSION > 4
300 static void
301 glog_func (const gchar *log_domain,
302 GLogLevelFlags log_level,
303 const gchar *message,
304 gpointer user_data)
306 old_glog_func (log_domain, log_level, message, user_data);
307 if (log_level & (G_LOG_LEVEL_ERROR
308 | G_LOG_LEVEL_CRITICAL
309 | G_LOG_LEVEL_WARNING))
311 JNIEnv *env = cp_gtk_gdk_env ();
312 jthrowable *exc = (*env)->ExceptionOccurred(env);
313 gchar *detail = g_strconcat (log_domain, ": ", message, NULL);
314 JCL_ThrowException (env, "java/lang/InternalError", detail);
315 g_free (detail);
316 (*env)->ExceptionDescribe (env);
317 if (exc != NULL)
318 (*env)->Throw (env, exc);
319 else
320 (*env)->ExceptionClear (env);
323 #endif
325 JNIEXPORT void JNICALL
326 Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkMain
327 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
329 gdk_threads_enter ();
331 gtk_main ();
333 gdk_threads_leave ();
337 static jint gdk_color_to_java_color (GdkColor color);
340 JNIEXPORT void JNICALL
341 Java_gnu_java_awt_peer_gtk_GtkToolkit_beep
342 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
344 gdk_threads_enter ();
346 gdk_beep ();
348 gdk_threads_leave ();
351 JNIEXPORT void JNICALL
352 Java_gnu_java_awt_peer_gtk_GtkToolkit_sync
353 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
355 gdk_threads_enter ();
357 gdk_flush ();
359 gdk_threads_leave ();
362 JNIEXPORT void JNICALL
363 Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenSizeDimensions
364 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
365 jintArray jdims)
367 jint *dims = (*env)->GetIntArrayElements (env, jdims, 0);
369 gdk_threads_enter ();
371 dims[0] = gdk_screen_width ();
372 dims[1] = gdk_screen_height ();
374 gdk_threads_leave ();
376 (*env)->ReleaseIntArrayElements(env, jdims, dims, 0);
379 JNIEXPORT jint JNICALL
380 Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenResolution
381 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
383 jint res;
385 gdk_threads_enter ();
387 res = gdk_screen_width () / (gdk_screen_width_mm () / 25.4);
389 gdk_threads_leave ();
391 return res;
394 #define CONVERT(type, state) \
395 gdk_color_to_java_color (style->type[GTK_STATE_ ## state])
397 JNIEXPORT void JNICALL
398 Java_gnu_java_awt_peer_gtk_GtkToolkit_loadSystemColors
399 (JNIEnv *env, jobject obj __attribute__((unused)),
400 jintArray jcolors)
402 jint *colors;
403 GtkStyle *style;
405 /* FIXME: this was deadlocking so assume it is thread-safe for now;
406 we need to replace this call with a .properties file anyway. */
407 #if 0
408 gdk_threads_enter ();
409 #endif
411 colors = (*env)->GetIntArrayElements (env, jcolors, 0);
413 style = gtk_widget_get_default_style ();
415 colors[AWT_DESKTOP] = CONVERT (bg, SELECTED);
416 colors[AWT_ACTIVE_CAPTION] = CONVERT (bg, SELECTED);
417 colors[AWT_ACTIVE_CAPTION_TEXT] = CONVERT (text, SELECTED);
418 colors[AWT_ACTIVE_CAPTION_BORDER] = CONVERT (fg, NORMAL);
419 colors[AWT_INACTIVE_CAPTION] = CONVERT (base, INSENSITIVE);
420 colors[AWT_INACTIVE_CAPTION_TEXT] = CONVERT (fg, INSENSITIVE);
421 colors[AWT_INACTIVE_CAPTION_BORDER] = CONVERT (fg, INSENSITIVE);
422 colors[AWT_WINDOW] = CONVERT (bg, NORMAL);
423 colors[AWT_WINDOW_BORDER] = CONVERT (fg, NORMAL);
424 colors[AWT_WINDOW_TEXT] = CONVERT (fg, NORMAL);
425 colors[AWT_MENU] = CONVERT (bg, NORMAL);
426 colors[AWT_MENU_TEXT] = CONVERT (fg, NORMAL);
427 colors[AWT_TEXT] = CONVERT (bg, NORMAL);
428 colors[AWT_TEXT_TEXT] = CONVERT (fg, NORMAL);
429 colors[AWT_TEXT_HIGHLIGHT] = CONVERT (bg, SELECTED);
430 colors[AWT_TEXT_HIGHLIGHT_TEXT] = CONVERT (fg, SELECTED);
431 colors[AWT_TEXT_INACTIVE_TEXT] = CONVERT (bg, INSENSITIVE);
432 colors[AWT_CONTROL] = CONVERT (bg, NORMAL);
433 colors[AWT_CONTROL_TEXT] = CONVERT (fg, NORMAL);
434 colors[AWT_CONTROL_HIGHLIGHT] = CONVERT (base, ACTIVE);
435 colors[AWT_CONTROL_LT_HIGHLIGHT] = CONVERT (bg, PRELIGHT);
436 colors[AWT_CONTROL_SHADOW] = CONVERT (bg, ACTIVE);
437 colors[AWT_CONTROL_DK_SHADOW] = CONVERT (fg, INSENSITIVE);
438 colors[AWT_SCROLLBAR] = CONVERT (base, INSENSITIVE);
439 colors[AWT_INFO] = CONVERT (bg, NORMAL);
440 colors[AWT_INFO_TEXT] = CONVERT (fg, NORMAL);
442 (*env)->ReleaseIntArrayElements(env, jcolors, colors, 0);
444 #if 0
445 gdk_threads_leave ();
446 #endif
449 #undef CONVERT
451 static jint
452 gdk_color_to_java_color (GdkColor gdk_color)
454 guchar red;
455 guchar green;
456 guchar blue;
457 float factor;
459 factor = 255.0 / 65535.0;
461 red = (float) gdk_color.red * factor;
462 green = (float) gdk_color.green * factor;
463 blue = (float) gdk_color.blue * factor;
465 return (jint) (0xff000000 | (red << 16) | (green << 8) | blue);