I tested the
Swing, AWT and Java2D demo as well as some JOGL pieces (which originally
caused problems with the JAWT Lock/Unlock functions) and those seem to
work well with this. Maybe turn on default after the release and weed
out issues in the following cycle.
Cheers, Roman
------------------------------------------------------------------------
Index: include/gnu_java_awt_peer_gtk_GtkToolkit.h
===================================================================
RCS file:
/cvsroot/classpath/classpath/include/gnu_java_awt_peer_gtk_GtkToolkit.h,v
retrieving revision 1.15
diff -u -1 -5 -r1.15 gnu_java_awt_peer_gtk_GtkToolkit.h
--- include/gnu_java_awt_peer_gtk_GtkToolkit.h 3 Jan 2007 22:51:07 -0000
1.15
+++ include/gnu_java_awt_peer_gtk_GtkToolkit.h 3 Apr 2007 13:38:54 -0000
@@ -1,28 +1,28 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#ifndef __gnu_java_awt_peer_gtk_GtkToolkit__
#define __gnu_java_awt_peer_gtk_GtkToolkit__
#include <jni.h>
#ifdef __cplusplus
extern "C"
{
#endif
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkInit (JNIEnv *env, jclass, jint);
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkInit (JNIEnv
*env, jclass, jint, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkMain (JNIEnv
*env, jclass);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkQuit (JNIEnv
*env, jclass);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_beep (JNIEnv
*env, jobject);
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenSizeDimensions (JNIEnv *env,
jobject, jintArray);
JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenResolution (JNIEnv *env,
jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_sync (JNIEnv
*env, jobject);
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_loadSystemColors
(JNIEnv *env, jobject, jintArray);
JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GtkToolkit_getLockState
(JNIEnv *env, jobject, jint);
JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_getMouseNumberOfButtons (JNIEnv *env,
jobject);
#ifdef __cplusplus
}
#endif
#endif /* __gnu_java_awt_peer_gtk_GtkToolkit__ */
Index: native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c
===================================================================
RCS file:
/cvsroot/classpath/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c,v
retrieving revision 1.33
diff -u -1 -5 -r1.33 gnu_java_awt_peer_gtk_GtkToolkit.c
--- native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c 29 Mar 2007
20:24:51 -0000 1.33
+++ native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c 3 Apr 2007
13:38:54 -0000
@@ -1,15 +1,16 @@
+
/* gtktoolkit.c -- Native portion of GtkToolkit
Copyright (C) 1998, 1999, 2005, 2007 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
@@ -76,104 +77,112 @@
#define VK_SHIFT 16
#define VK_CONTROL 17
#define VK_ALT 18
#define VK_CAPS_LOCK 20
#define VK_META 157
struct state_table *cp_gtk_native_state_table;
struct state_table *cp_gtk_native_global_ref_table;
static jclass gtkgenericpeer;
static jclass gtktoolkit;
static JavaVM *java_vm;
static jmethodID printCurrentThreadID;
static jmethodID setRunningID;
+/**
+ * The global AWT lock object.
+ */
+static jobject global_lock;
+
union env_union
{
void *void_env;
JNIEnv *jni_env;
};
JNIEnv *
cp_gtk_gdk_env()
{
union env_union tmp;
g_assert((*java_vm)->GetEnv(java_vm, &tmp.void_env, JNI_VERSION_1_2) ==
JNI_OK);
return tmp.jni_env;
}
GtkWindowGroup *cp_gtk_global_window_group;
double cp_gtk_dpi_conversion_factor;
-static void init_glib_threads(JNIEnv *, jint);
+static void jni_lock_cb();
+static void jni_unlock_cb();
+static void init_glib_threads(JNIEnv *, jint, jobject);
static gboolean post_set_running_flag (gpointer);
static gboolean set_running_flag (gpointer);
static gboolean clear_running_flag (gpointer);
static void init_dpi_conversion_factor (void);
static void dpi_changed_cb (GtkSettings *settings,
GParamSpec *pspec);
#if GTK_MINOR_VERSION > 4
static GLogFunc old_glog_func;
static void glog_func (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data);
#endif
/*
* Call gtk_init. It is very important that this happen before any other
* gtk calls.
*
* The portableNativeSync argument may have the values:
* 1 if the Java property gnu.classpath.awt.gtk.portable.native.sync
* is set to "true".
* 0 if it is set to "false"
* -1 if unset.
*/
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkInit (JNIEnv *env,
jclass clazz __attribute__((unused)),
- jint portableNativeSync)
+ jint portableNativeSync,
+ jobject lock)
{
int argc = 1;
char **argv;
char *homedir, *rcpath = NULL;
gtkgenericpeer = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GtkGenericPeer");
gtkgenericpeer = (*env)->NewGlobalRef(env, gtkgenericpeer);
printCurrentThreadID = (*env)->GetStaticMethodID (env, gtkgenericpeer,
"printCurrentThread",
"()V");
NSA_INIT (env, gtkgenericpeer);
g_assert((*env)->GetJavaVM(env, &java_vm) == 0);
/* GTK requires a program's argc and argv variables, and requires that they
be valid. Set it up. */
argv = (char **) g_malloc (sizeof (char *) * 2);
argv[0] = (char *) g_malloc(1);
argv[0][0] = '\0';
argv[1] = NULL;
- init_glib_threads(env, portableNativeSync);
+ init_glib_threads(env, portableNativeSync, lock);
/* From GDK 2.0 onwards we have to explicitly call gdk_threads_init */
gdk_threads_init();
gtk_init (&argc, &argv);
#if SYNCHRONIZE_GDK
XSynchronize (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), True);
#endif
gtk_widget_set_default_colormap (gdk_rgb_get_colormap ());
/* Make sure queued calls don't get sent to GTK/GDK while
we're shutting down. */
atexit (gdk_threads_enter);
@@ -203,56 +212,84 @@
cp_gtk_list_init_jni ();
cp_gtk_menuitem_init_jni ();
cp_gtk_scrollbar_init_jni ();
cp_gtk_textcomponent_init_jni ();
cp_gtk_window_init_jni ();
cp_gtk_global_window_group = gtk_window_group_new ();
init_dpi_conversion_factor ();
gtktoolkit = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GtkMainThread");
setRunningID = (*env)->GetStaticMethodID (env, gtktoolkit,
"setRunning", "(Z)V");
}
+/**
+ * A callback function that implements gdk_threads_enter(). This is
+ * implemented to wrap the JNI MonitorEnter() function.
+ */
+static void jni_lock_cb()
+{
+ JNIEnv * env = cp_gtk_gdk_env();
+ if ((*env)->MonitorEnter(env, global_lock) != JNI_OK)
+ {
+ printf("failure while entering GTK monitor\n");
+ }
+}
+
+/**
+ * A callback function that implements gdk_threads_leave(). This is
+ * implemented to wrap the JNI MonitorExit() function.
+ */
+static void jni_unlock_cb()
+{
+
+ JNIEnv * env = cp_gtk_gdk_env();
+ if ((*env)->MonitorExit(env, global_lock))
+ {
+ printf("failure while exiting GTK monitor\n");
+ }
+}
/** Initialize GLIB's threads properly, based on the value of the
gnu.classpath.awt.gtk.portable.native.sync Java system property. If
that's unset, use the PORTABLE_NATIVE_SYNC config.h macro. (TODO:
In some release following 0.10, that config.h macro will go away.)
*/
static void
-init_glib_threads(JNIEnv *env, jint portableNativeSync)
+init_glib_threads(JNIEnv *env, jint portableNativeSync, jobject lock)
{
if (portableNativeSync < 0)
{
#ifdef PORTABLE_NATIVE_SYNC /* Default value, if not set by the Java system
property */
portableNativeSync = 1;
#else
portableNativeSync = 0;
#endif
}
(*env)->GetJavaVM( env, &cp_gtk_the_vm );
if (!g_thread_supported ())
{
if (portableNativeSync)
- g_thread_init ( &cp_gtk_portable_native_sync_jni_functions );
- else
- g_thread_init ( NULL );
+ {
+ global_lock = lock;
+ gdk_threads_set_lock_functions(&jni_lock_cb, &jni_unlock_cb);
+ }
+ g_thread_init(NULL);
}
else
{
/* Warn if portable native sync is desired but the threading
system is already initialized. In that case we can't
override the threading implementation with our portable
native sync functions. */
if (portableNativeSync)
g_printerr ("peer warning: portable native sync disabled.\n");
}
/* Debugging progress message; uncomment if needed: */
/* printf("called gthread init\n"); */
}
@@ -324,38 +361,38 @@
JCL_ThrowException (env, "java/lang/InternalError", detail);
g_free (detail);
(*env)->ExceptionDescribe (env);
if (exc != NULL)
(*env)->Throw (env, exc);
else
(*env)->ExceptionClear (env);
}
}
#endif
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkMain
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
{
- gdk_threads_enter ();
+ gdk_threads_enter();
gtk_init_add (post_set_running_flag, NULL);
gtk_quit_add (gtk_main_level (), clear_running_flag, NULL);
gtk_main ();
- gdk_threads_leave ();
+ gdk_threads_leave();
}
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkQuit
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
{
gdk_threads_enter ();
gtk_main_quit ();
gdk_threads_leave ();
}
static jint gdk_color_to_java_color (GdkColor color);
@@ -579,15 +616,16 @@
{
(*cp_gtk_gdk_env ())->CallStaticVoidMethod (cp_gtk_gdk_env (),
gtktoolkit,
setRunningID, TRUE);
return FALSE;
}
static gboolean
clear_running_flag (gpointer data __attribute__((unused)))
{
(*cp_gtk_gdk_env ())->CallStaticVoidMethod (cp_gtk_gdk_env (),
gtktoolkit,
setRunningID, FALSE);
return FALSE;
}
+
Index: gnu/java/awt/peer/gtk/GtkToolkit.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java,v
retrieving revision 1.100
diff -u -1 -5 -r1.100 GtkToolkit.java
--- gnu/java/awt/peer/gtk/GtkToolkit.java 12 Feb 2007 21:39:20 -0000
1.100
+++ gnu/java/awt/peer/gtk/GtkToolkit.java 3 Apr 2007 13:38:54 -0000
@@ -122,54 +122,57 @@
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import javax.imageio.spi.IIORegistry;
/* This class uses a deprecated method java.awt.peer.ComponentPeer.getPeer().
This merits comment. We are basically calling Sun's bluff on this one.
We think Sun has deprecated it simply to discourage its use as it is
bad programming style. However, we need to get at a component's peer in
this class. If getPeer() ever goes away, we can implement a hash table
that will keep up with every window's peer, but for now this is faster. */
public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
{
+ static final Object GTK_LOCK;
+
private static EventQueue q;
- static native void gtkInit(int portableNativeSync);
+ static native void gtkInit(int portableNativeSync, Object lock);
static native void gtkMain();
static native void gtkQuit();
static
{
System.loadLibrary("gtkpeer");
int portableNativeSync;
String portNatSyncProp =
System.getProperty("gnu.classpath.awt.gtk.portable.native.sync");
if (portNatSyncProp == null)
portableNativeSync = -1; // unset
else if (Boolean.valueOf(portNatSyncProp).booleanValue())
portableNativeSync = 1; // true
else
portableNativeSync = 0; // false
-
- gtkInit(portableNativeSync);
+
+ GTK_LOCK = new String("GTK LOCK");
+ gtkInit(portableNativeSync, GTK_LOCK);
}
public GtkToolkit ()
{
}
public native void beep();
private native void getScreenSizeDimensions(int[] xy);
public int checkImage (Image image, int width, int height,
ImageObserver observer)
{
int status = ImageObserver.ALLBITS
| ImageObserver.WIDTH