gnu_java_awt_peer_gtk_GtkToolkit.c [plain text]
#include "gtkpeer.h"
#include "gnu_java_awt_peer_gtk_GtkToolkit.h"
#include "gthread-jni.h"
#include <sys/time.h>
#ifdef JVM_SUN
struct state_table *native_state_table;
struct state_table *native_global_ref_table;
#endif
jmethodID setBoundsCallbackID;
jmethodID postActionEventID;
jmethodID postMenuActionEventID;
jmethodID postMouseEventID;
jmethodID postConfigureEventID;
jmethodID postExposeEventID;
jmethodID postKeyEventID;
jmethodID postFocusEventID;
jmethodID postAdjustmentEventID;
jmethodID postItemEventID;
jmethodID choicePostItemEventID;
jmethodID postListItemEventID;
jmethodID postTextEventID;
jmethodID postWindowEventID;
jmethodID postInsetsChangedEventID;
jmethodID windowGetWidthID;
jmethodID windowGetHeightID;
jmethodID beginNativeRepaintID;
jmethodID endNativeRepaintID;
jmethodID initComponentGraphicsID;
jmethodID initComponentGraphics2DID;
jmethodID setCursorID;
JavaVM *java_vm;
union env_union
{
void *void_env;
JNIEnv *jni_env;
};
JNIEnv *
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 *global_gtk_window_group;
static void init_glib_threads(JNIEnv *, jint);
double dpi_conversion_factor;
static void init_dpi_conversion_factor (void);
static void dpi_changed_cb (GtkSettings *settings,
GParamSpec *pspec);
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_gtkInit (JNIEnv *env,
jclass clazz __attribute__((unused)),
jint portableNativeSync)
{
int argc = 1;
char **argv;
char *homedir, *rcpath = NULL;
jclass gtkgenericpeer, gtkcomponentpeer, gtkchoicepeer, gtkwindowpeer, gtkscrollbarpeer, gtklistpeer,
gtkmenuitempeer, gtktextcomponentpeer, window, gdkgraphics, gdkgraphics2d;
gtkgenericpeer = (*env)->FindClass(env, "gnu/java/awt/peer/gtk/GtkGenericPeer");
NSA_INIT (env, gtkgenericpeer);
g_assert((*env)->GetJavaVM(env, &java_vm) == 0);
argv = (char **) g_malloc (sizeof (char *) * 2);
argv[0] = (char *) g_malloc(1);
#if 1
strcpy(argv[0], "");
#else
argv[0][0] = '\0';
#endif
argv[1] = NULL;
init_glib_threads(env, portableNativeSync);
gdk_threads_init();
gtk_init (&argc, &argv);
gdk_rgb_init ();
gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
gtk_widget_set_default_visual (gdk_rgb_get_visual ());
atexit (gdk_threads_enter);
gdk_event_handler_set ((GdkEventFunc)awt_event_handler, NULL, NULL);
if ((homedir = getenv ("HOME")))
{
rcpath = (char *) g_malloc (strlen (homedir) + strlen (RC_FILE) + 2);
sprintf (rcpath, "%s/%s", homedir, RC_FILE);
}
gtk_rc_parse ((rcpath) ? rcpath : RC_FILE);
g_free (rcpath);
g_free (argv[0]);
g_free (argv);
window = (*env)->FindClass (env, "java/awt/Window");
gtkcomponentpeer = (*env)->FindClass (env,
"gnu/java/awt/peer/gtk/GtkComponentPeer");
gtkchoicepeer = (*env)->FindClass (env,
"gnu/java/awt/peer/gtk/GtkChoicePeer");
gtkwindowpeer = (*env)->FindClass (env,
"gnu/java/awt/peer/gtk/GtkWindowPeer");
gtkscrollbarpeer = (*env)->FindClass (env,
"gnu/java/awt/peer/gtk/GtkScrollbarPeer");
gtklistpeer = (*env)->FindClass (env, "gnu/java/awt/peer/gtk/GtkListPeer");
gtkmenuitempeer = (*env)->FindClass (env,
"gnu/java/awt/peer/gtk/GtkMenuItemPeer");
gtktextcomponentpeer = (*env)->FindClass (env,
"gnu/java/awt/peer/gtk/GtkTextComponentPeer");
gdkgraphics = (*env)->FindClass (env,
"gnu/java/awt/peer/gtk/GdkGraphics");
gdkgraphics2d = (*env)->FindClass (env,
"gnu/java/awt/peer/gtk/GdkGraphics2D");
setBoundsCallbackID = (*env)->GetMethodID (env, window,
"setBoundsCallback",
"(IIII)V");
postMenuActionEventID = (*env)->GetMethodID (env, gtkmenuitempeer,
"postMenuActionEvent",
"()V");
postMouseEventID = (*env)->GetMethodID (env, gtkcomponentpeer,
"postMouseEvent", "(IJIIIIZ)V");
setCursorID = (*env)->GetMethodID (env, gtkcomponentpeer,
"setCursor", "()V");
beginNativeRepaintID = (*env)->GetMethodID (env, gtkcomponentpeer,
"beginNativeRepaint", "()V");
endNativeRepaintID = (*env)->GetMethodID (env, gtkcomponentpeer,
"endNativeRepaint", "()V");
postConfigureEventID = (*env)->GetMethodID (env, gtkwindowpeer,
"postConfigureEvent", "(IIII)V");
postWindowEventID = (*env)->GetMethodID (env, gtkwindowpeer,
"postWindowEvent",
"(ILjava/awt/Window;I)V");
postInsetsChangedEventID = (*env)->GetMethodID (env, gtkwindowpeer,
"postInsetsChangedEvent",
"(IIII)V");
windowGetWidthID = (*env)->GetMethodID (env, gtkwindowpeer,
"getWidth", "()I");
windowGetHeightID = (*env)->GetMethodID (env, gtkwindowpeer,
"getHeight", "()I");
postExposeEventID = (*env)->GetMethodID (env, gtkcomponentpeer,
"postExposeEvent", "(IIII)V");
postKeyEventID = (*env)->GetMethodID (env, gtkcomponentpeer,
"postKeyEvent", "(IJIICI)V");
postFocusEventID = (*env)->GetMethodID (env, gtkcomponentpeer,
"postFocusEvent", "(IZ)V");
postAdjustmentEventID = (*env)->GetMethodID (env, gtkscrollbarpeer,
"postAdjustmentEvent",
"(II)V");
postItemEventID = (*env)->GetMethodID (env, gtkcomponentpeer,
"postItemEvent",
"(Ljava/lang/Object;I)V");
choicePostItemEventID = (*env)->GetMethodID (env, gtkchoicepeer,
"choicePostItemEvent",
"(Ljava/lang/String;I)V");
postListItemEventID = (*env)->GetMethodID (env, gtklistpeer,
"postItemEvent",
"(II)V");
postTextEventID = (*env)->GetMethodID (env, gtktextcomponentpeer,
"postTextEvent",
"()V");
initComponentGraphicsID = (*env)->GetMethodID (env, gdkgraphics,
"initComponentGraphics",
"()V");
initComponentGraphics2DID = (*env)->GetMethodID (env, gdkgraphics2d,
"initComponentGraphics2D",
"()V");
global_gtk_window_group = gtk_window_group_new ();
init_dpi_conversion_factor ();
}
static void
init_glib_threads(JNIEnv *env, jint portableNativeSync)
{
if (portableNativeSync < 0)
{
#ifdef PORTABLE_NATIVE_SYNC
portableNativeSync = 1;
#else
portableNativeSync = 0;
#endif
}
(*env)->GetJavaVM( env, &the_vm );
if (!g_thread_supported ())
{
if (portableNativeSync)
g_thread_init ( &portable_native_sync_jni_functions );
else
g_thread_init ( NULL );
}
else
{
if (portableNativeSync)
g_printerr ("peer warning: portable native sync disabled.\n");
}
}
static void
init_dpi_conversion_factor ()
{
GtkSettings *settings = gtk_settings_get_default ();
GObjectClass *klass;
klass = G_OBJECT_CLASS (GTK_SETTINGS_GET_CLASS (settings));
if (g_object_class_find_property (klass, "gtk-xft-dpi"))
{
int int_dpi;
g_object_get (settings, "gtk-xft-dpi", &int_dpi, NULL);
if (int_dpi < 0)
dpi_conversion_factor = PANGO_SCALE * 72.0 / 96.;
else
dpi_conversion_factor = PANGO_SCALE * 72.0 / (int_dpi / PANGO_SCALE);
g_signal_connect (settings, "notify::gtk-xft-dpi",
G_CALLBACK (dpi_changed_cb), NULL);
}
else
dpi_conversion_factor = PANGO_SCALE * 72.0 / 96.;
}
static void
dpi_changed_cb (GtkSettings *settings,
GParamSpec *pspec __attribute__((unused)))
{
int int_dpi;
g_object_get (settings, "gtk-xft-dpi", &int_dpi, NULL);
if (int_dpi < 0)
dpi_conversion_factor = PANGO_SCALE * 72.0 / 96.;
else
dpi_conversion_factor = PANGO_SCALE * 72.0 / (int_dpi / PANGO_SCALE);
}
static int
within_human_latency_tolerance(struct timeval *init)
{
struct timeval curr;
unsigned long milliseconds_elapsed;
gettimeofday(&curr, NULL);
milliseconds_elapsed = (((curr.tv_sec * 1000) + (curr.tv_usec / 1000))
- ((init->tv_sec * 1000) + (init->tv_usec / 1000)));
return milliseconds_elapsed < 100;
}
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_iterateNativeQueue
(JNIEnv *env,
jobject self __attribute__((unused)),
jobject lockedQueue,
jboolean block)
{
struct timeval init;
gettimeofday(&init, NULL);
gdk_threads_enter ();
(*env)->MonitorExit (env, lockedQueue);
if (block)
{
do
gtk_main_iteration ();
while (within_human_latency_tolerance (&init)
&& gtk_events_pending ());
}
else
{
while (within_human_latency_tolerance (&init)
&& gtk_events_pending ())
gtk_main_iteration ();
}
(*env)->MonitorEnter (env, lockedQueue);
gdk_threads_leave ();
}
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_wakeNativeQueue
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
{
g_main_context_wakeup (NULL);
}
JNIEXPORT jboolean JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_nativeQueueEmpty
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
{
jboolean empty = FALSE;
gdk_threads_enter ();
empty = ! gtk_events_pending();
gdk_threads_leave ();
return empty;
}
static jint gdk_color_to_java_color (GdkColor color);
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_beep
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
{
gdk_threads_enter ();
gdk_beep ();
gdk_threads_leave ();
}
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_sync
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
{
gdk_threads_enter ();
gdk_flush ();
gdk_threads_leave ();
}
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenSizeDimensions
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
jintArray jdims)
{
jint *dims = (*env)->GetIntArrayElements (env, jdims, 0);
gdk_threads_enter ();
dims[0] = gdk_screen_width ();
dims[1] = gdk_screen_height ();
gdk_threads_leave ();
(*env)->ReleaseIntArrayElements(env, jdims, dims, 0);
}
JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_getScreenResolution
(JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)))
{
jint res;
gdk_threads_enter ();
res = gdk_screen_width () / (gdk_screen_width_mm () / 25.4);
gdk_threads_leave ();
return res;
}
#define CONVERT(type, state) \
gdk_color_to_java_color (style->type[GTK_STATE_ ## state])
JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkToolkit_loadSystemColors
(JNIEnv *env, jobject obj __attribute__((unused)),
jintArray jcolors)
{
jint *colors;
GtkStyle *style;
colors = (*env)->GetIntArrayElements (env, jcolors, 0);
gdk_threads_enter ();
style = gtk_widget_get_default_style ();
colors[AWT_DESKTOP] = CONVERT (bg, SELECTED);
colors[AWT_ACTIVE_CAPTION] = CONVERT (bg, SELECTED);
colors[AWT_ACTIVE_CAPTION_TEXT] = CONVERT (text, SELECTED);
colors[AWT_ACTIVE_CAPTION_BORDER] = CONVERT (fg, NORMAL);
colors[AWT_INACTIVE_CAPTION] = CONVERT (base, INSENSITIVE);
colors[AWT_INACTIVE_CAPTION_TEXT] = CONVERT (fg, INSENSITIVE);
colors[AWT_INACTIVE_CAPTION_BORDER] = CONVERT (fg, INSENSITIVE);
colors[AWT_WINDOW] = CONVERT (bg, NORMAL);
colors[AWT_WINDOW_BORDER] = CONVERT (fg, NORMAL);
colors[AWT_WINDOW_TEXT] = CONVERT (fg, NORMAL);
colors[AWT_MENU] = CONVERT (bg, NORMAL);
colors[AWT_MENU_TEXT] = CONVERT (fg, NORMAL);
colors[AWT_TEXT] = CONVERT (bg, NORMAL);
colors[AWT_TEXT_TEXT] = CONVERT (fg, NORMAL);
colors[AWT_TEXT_HIGHLIGHT] = CONVERT (bg, SELECTED);
colors[AWT_TEXT_HIGHLIGHT_TEXT] = CONVERT (fg, SELECTED);
colors[AWT_TEXT_INACTIVE_TEXT] = CONVERT (bg, INSENSITIVE);
colors[AWT_CONTROL] = CONVERT (bg, NORMAL);
colors[AWT_CONTROL_TEXT] = CONVERT (fg, NORMAL);
colors[AWT_CONTROL_HIGHLIGHT] = CONVERT (base, ACTIVE);
colors[AWT_CONTROL_LT_HIGHLIGHT] = CONVERT (bg, PRELIGHT);
colors[AWT_CONTROL_SHADOW] = CONVERT (bg, ACTIVE);
colors[AWT_CONTROL_DK_SHADOW] = CONVERT (fg, INSENSITIVE);
colors[AWT_SCROLLBAR] = CONVERT (base, INSENSITIVE);
colors[AWT_INFO] = CONVERT (bg, NORMAL);
colors[AWT_INFO_TEXT] = CONVERT (fg, NORMAL);
gdk_threads_leave ();
(*env)->ReleaseIntArrayElements(env, jcolors, colors, 0);
}
#undef CONVERT
static jint
gdk_color_to_java_color (GdkColor gdk_color)
{
guchar red;
guchar green;
guchar blue;
float factor;
factor = 255.0 / 65535.0;
red = (float) gdk_color.red * factor;
green = (float) gdk_color.green * factor;
blue = (float) gdk_color.blue * factor;
return (jint) (0xff000000 | (red << 16) | (green << 8) | blue);
}