diff options
Diffstat (limited to 'libjava/jni/gtk-peer')
27 files changed, 1618 insertions, 1615 deletions
diff --git a/libjava/jni/gtk-peer/gdkfont.h b/libjava/jni/gtk-peer/gdkfont.h index 792cee4..3370152 100644 --- a/libjava/jni/gtk-peer/gdkfont.h +++ b/libjava/jni/gtk-peer/gdkfont.h @@ -102,6 +102,21 @@ extern struct state_table *native_text_layout_state_table; #define TEXT_METRICS_Y_ADVANCE 5 #define NUM_TEXT_METRICS 6 +#define NUM_GLYPH_METRICS 10 + +#define GLYPH_LOG_X(i) (NUM_GLYPH_METRICS * (i) ) +#define GLYPH_LOG_Y(i) (NUM_GLYPH_METRICS * (i) + 1) +#define GLYPH_LOG_WIDTH(i) (NUM_GLYPH_METRICS * (i) + 2) +#define GLYPH_LOG_HEIGHT(i) (NUM_GLYPH_METRICS * (i) + 3) + +#define GLYPH_INK_X(i) (NUM_GLYPH_METRICS * (i) + 4) +#define GLYPH_INK_Y(i) (NUM_GLYPH_METRICS * (i) + 5) +#define GLYPH_INK_WIDTH(i) (NUM_GLYPH_METRICS * (i) + 6) +#define GLYPH_INK_HEIGHT(i) (NUM_GLYPH_METRICS * (i) + 7) + +#define GLYPH_POS_X(i) (NUM_GLYPH_METRICS * (i) + 8) +#define GLYPH_POS_Y(i) (NUM_GLYPH_METRICS * (i) + 9) + struct peerfont { PangoFont *font; @@ -119,16 +134,6 @@ struct peerfont void *graphics_resource; }; -struct glyphvec -{ - /* the GList is list of PangoGlyphItems, each of which is a pair of 1 - PangoItem and 1 PangoGlyphString. */ - GList *glyphitems; - PangoFontDescription *desc; - PangoFont *font; - PangoContext *ctx; -}; - struct textlayout { PangoLayout *pango_layout; diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c index c94e664..7787eb4 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c @@ -49,7 +49,7 @@ exception statement from your version. */ */ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GThreadNativeMethodRunner_nativeRun - (JNIEnv *gdk_env __attribute__((unused)), + (JNIEnv *env __attribute__((unused)), jobject lcl_obj __attribute__((unused)), jlong funcAddr, jlong funcArg) { diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontMetrics.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontMetrics.c deleted file mode 100644 index 5248938..0000000 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontMetrics.c +++ /dev/null @@ -1,115 +0,0 @@ -/* gdkfontmetrics.c - Copyright (C) 1999, 2003, 2004 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. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -#include "gtkpeer.h" -#include "gdkfont.h" - -#include "gnu_java_awt_peer_gtk_GdkFontMetrics.h" -#include <gdk/gdkx.h> - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkFontMetrics_getPeerFontMetrics - (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject java_font, jdoubleArray java_metrics) -{ - struct peerfont *pfont = NULL; - jdouble *native_metrics = NULL; - PangoFontMetrics *pango_metrics; - - gdk_threads_enter(); - - pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); - g_assert (pfont != NULL); - - pango_metrics = pango_context_get_metrics (pfont->ctx, pfont->desc, - gtk_get_default_language ()); - - native_metrics = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); - g_assert (native_metrics != NULL); - - native_metrics[FONT_METRICS_ASCENT] = PANGO_PIXELS (pango_font_metrics_get_ascent (pango_metrics)); - native_metrics[FONT_METRICS_MAX_ASCENT] = native_metrics[FONT_METRICS_ASCENT]; - native_metrics[FONT_METRICS_DESCENT] = PANGO_PIXELS (pango_font_metrics_get_descent (pango_metrics)); - if (native_metrics[FONT_METRICS_DESCENT] < 0) - native_metrics[FONT_METRICS_DESCENT] = - native_metrics[FONT_METRICS_DESCENT]; - native_metrics[FONT_METRICS_MAX_DESCENT] = native_metrics[FONT_METRICS_DESCENT]; - native_metrics[FONT_METRICS_MAX_ADVANCE] = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width (pango_metrics)); - - (*env)->ReleaseDoubleArrayElements (env, java_metrics, native_metrics, 0); - - pango_font_metrics_unref (pango_metrics); - - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkFontMetrics_getPeerTextMetrics - (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject java_font, jstring str, jdoubleArray java_metrics) -{ - struct peerfont *pfont = NULL; - const char *cstr = NULL; - jdouble *native_metrics = NULL; - PangoRectangle log; - - gdk_threads_enter(); - - pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, java_font); - g_assert (pfont != NULL); - - cstr = (*env)->GetStringUTFChars (env, str, NULL); - g_assert(cstr != NULL); - - pango_layout_set_text (pfont->layout, cstr, -1); - pango_layout_get_extents (pfont->layout, NULL, &log); - - (*env)->ReleaseStringUTFChars (env, str, cstr); - pango_layout_set_text (pfont->layout, "", -1); - - native_metrics = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); - g_assert (native_metrics != NULL); - - native_metrics[TEXT_METRICS_X_BEARING] = PANGO_PIXELS(log.x); - native_metrics[TEXT_METRICS_Y_BEARING] = PANGO_PIXELS(log.y); - native_metrics[TEXT_METRICS_WIDTH] = PANGO_PIXELS(log.width); - native_metrics[TEXT_METRICS_HEIGHT] = PANGO_PIXELS(log.height); - native_metrics[TEXT_METRICS_X_ADVANCE] = PANGO_PIXELS(log.x + log.width); - native_metrics[TEXT_METRICS_Y_ADVANCE] = PANGO_PIXELS(log.y + log.height); - - (*env)->ReleaseDoubleArrayElements (env, java_metrics, native_metrics, 0); - - gdk_threads_leave(); -} - diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c index d992653..7a8a2ce 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c @@ -40,23 +40,6 @@ struct state_table *native_font_state_table; -/* -rough sketch of the mapping between java and -pango text objects: - - Font <-> - PangoFont - - PangoFontDescription - - PangoContext - - PangoLayout (for rendering and measuring) - - GlyphVector <-> - GList of PangoGlyphItem - - PangoFontDescription - - PangoContext - - FontRenderContext <-> stays in plain java - -*/ - enum java_awt_font_style { java_awt_font_PLAIN = 0, java_awt_font_BOLD = 1, @@ -69,11 +52,22 @@ enum java_awt_font_baseline { java_awt_font_HANGING_BASELINE = 2 }; +static jmethodID glyphVector_ctor; +static jclass glyphVector_class; +static PangoAttrList *attrs = NULL; + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_initStaticState (JNIEnv *env, jclass clazz) { NSA_FONT_INIT (env, clazz); + + glyphVector_class = (*env)->FindClass + (env, "gnu/java/awt/peer/gtk/GdkGlyphVector"); + + glyphVector_ctor = (*env)->GetMethodID + (env, glyphVector_class, "<init>", + "([D[ILjava/awt/Font;Ljava/awt/font/FontRenderContext;)V"); } JNIEXPORT void JNICALL @@ -111,6 +105,223 @@ Java_gnu_java_awt_peer_gtk_GdkFontPeer_dispose gdk_threads_leave (); } + +JNIEXPORT jobject JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_getGlyphVector + (JNIEnv *env, jobject self, + jstring chars, + jobject font, + jobject fontRenderContext) +{ + struct peerfont *pfont = NULL; + GList *items = NULL, *i = NULL; + gchar *str = NULL; + int len, j; + double *native_extents; + int *native_codes; + jintArray java_codes = NULL; + jdoubleArray java_extents = NULL; + + gdk_threads_enter (); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self); + g_assert (pfont != NULL); + + len = (*gdk_env())->GetStringUTFLength (env, chars); + str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL); + g_assert (str != NULL); + + if (attrs == NULL) + attrs = pango_attr_list_new (); + + if (len > 0 && str[len-1] == '\0') + len--; + + items = pango_itemize (pfont->ctx, str, 0, len, attrs, NULL); + + i = g_list_first (items); + + if (i == NULL) + { + java_extents = (*env)->NewDoubleArray (env, 0); + java_codes = (*env)->NewIntArray (env, 0); + } + else + { + PangoGlyphString *glyphs; + PangoItem *item = (PangoItem *)i->data; + + pango_context_set_font_description (pfont->ctx, pfont->desc); + pango_context_set_language (pfont->ctx, gtk_get_default_language()); + pango_context_load_font (pfont->ctx, pfont->desc); + + glyphs = pango_glyph_string_new (); + g_assert (glyphs != NULL); + + pango_shape (str + item->offset, item->length, + &(item->analysis), glyphs); + + if (glyphs->num_glyphs > 0) + { + int x = 0; + double scale = ((double) PANGO_SCALE); + + java_extents = (*env)->NewDoubleArray (env, glyphs->num_glyphs * NUM_GLYPH_METRICS); + java_codes = (*env)->NewIntArray (env, glyphs->num_glyphs); + native_extents = (*env)->GetDoubleArrayElements (env, java_extents, NULL); + native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); + + for (j = 0; j < glyphs->num_glyphs; ++j) + { + PangoRectangle ink; + PangoRectangle logical; + PangoGlyphGeometry *geom = &glyphs->glyphs[j].geometry; + + pango_font_get_glyph_extents (pfont->font, + glyphs->glyphs[j].glyph, + &ink, &logical); + + native_codes[j] = glyphs->glyphs[j].glyph; + + native_extents[ GLYPH_LOG_X(j) ] = (logical.x) / scale; + native_extents[ GLYPH_LOG_Y(j) ] = (- logical.y) / scale; + native_extents[ GLYPH_LOG_WIDTH(j) ] = (logical.width) / scale; + native_extents[ GLYPH_LOG_HEIGHT(j) ] = (logical.height) / scale; + + native_extents[ GLYPH_INK_X(j) ] = (ink.x) / scale; + native_extents[ GLYPH_INK_Y(j) ] = (- ink.y) / scale; + native_extents[ GLYPH_INK_WIDTH(j) ] = (ink.width) / scale; + native_extents[ GLYPH_INK_HEIGHT(j) ] = (ink.height) / scale; + + native_extents[ GLYPH_POS_X(j) ] = (x + geom->x_offset) / scale; + native_extents[ GLYPH_POS_Y(j) ] = ( - geom->y_offset) / scale; + + x += geom->width; + } + (*env)->ReleaseDoubleArrayElements (env, java_extents, native_extents, 0); + (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); + } + + pango_glyph_string_free (glyphs); + } + + (*env)->ReleaseStringUTFChars (env, chars, str); + + for (i = g_list_first (items); i != NULL; i = g_list_next (i)) + g_free (i->data); + + g_list_free (items); + + gdk_threads_leave (); + + return (*env)->NewObject (env, + glyphVector_class, + glyphVector_ctor, + java_extents, java_codes, + font, fontRenderContext); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_getFontMetrics + (JNIEnv *env, jobject java_font, jdoubleArray java_metrics) +{ + struct peerfont *pfont = NULL; + jdouble *native_metrics = NULL; + PangoFontMetrics *pango_metrics; + + gdk_threads_enter(); + + pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, java_font); + g_assert (pfont != NULL); + + pango_metrics + = pango_context_get_metrics (pfont->ctx, pfont->desc, + gtk_get_default_language ()); + + native_metrics + = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); + + g_assert (native_metrics != NULL); + + native_metrics[FONT_METRICS_ASCENT] + = PANGO_PIXELS (pango_font_metrics_get_ascent (pango_metrics)); + + native_metrics[FONT_METRICS_MAX_ASCENT] + = native_metrics[FONT_METRICS_ASCENT]; + + native_metrics[FONT_METRICS_DESCENT] + = PANGO_PIXELS (pango_font_metrics_get_descent (pango_metrics)); + + if (native_metrics[FONT_METRICS_DESCENT] < 0) + native_metrics[FONT_METRICS_DESCENT] + = - native_metrics[FONT_METRICS_DESCENT]; + + native_metrics[FONT_METRICS_MAX_DESCENT] + = native_metrics[FONT_METRICS_DESCENT]; + + native_metrics[FONT_METRICS_MAX_ADVANCE] + = PANGO_PIXELS (pango_font_metrics_get_approximate_char_width + (pango_metrics)); + + (*env)->ReleaseDoubleArrayElements (env, + java_metrics, + native_metrics, 0); + + pango_font_metrics_unref (pango_metrics); + + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkFontPeer_getTextMetrics + (JNIEnv *env, jobject java_font, jstring str, jdoubleArray java_metrics) +{ + struct peerfont *pfont = NULL; + const char *cstr = NULL; + jdouble *native_metrics = NULL; + PangoRectangle log; + + gdk_threads_enter(); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, java_font); + g_assert (pfont != NULL); + + cstr = (*env)->GetStringUTFChars (env, str, NULL); + g_assert(cstr != NULL); + + pango_layout_set_text (pfont->layout, cstr, -1); + pango_layout_get_extents (pfont->layout, NULL, &log); + + (*env)->ReleaseStringUTFChars (env, str, cstr); + pango_layout_set_text (pfont->layout, "", -1); + + native_metrics = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); + g_assert (native_metrics != NULL); + + native_metrics[TEXT_METRICS_X_BEARING] + = PANGO_PIXELS( ((double)log.x) ); + + native_metrics[TEXT_METRICS_Y_BEARING] + = PANGO_PIXELS( ((double)log.y) ); + + native_metrics[TEXT_METRICS_WIDTH] + = PANGO_PIXELS( ((double)log.width) ); + + native_metrics[TEXT_METRICS_HEIGHT] + = PANGO_PIXELS( ((double)log.height) ); + + native_metrics[TEXT_METRICS_X_ADVANCE] + = PANGO_PIXELS( ((double) (log.x + log.width)) ); + + native_metrics[TEXT_METRICS_Y_ADVANCE] + = PANGO_PIXELS( ((double) (log.y + log.height)) ); + + (*env)->ReleaseDoubleArrayElements (env, java_metrics, native_metrics, 0); + + gdk_threads_leave(); +} + + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont (JNIEnv *env, jobject self, jstring family_name_str, jint style_int, jint size, jboolean useGraphics2D) @@ -142,7 +353,6 @@ Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont pango_font_description_set_family (pfont->desc, family_name); (*env)->ReleaseStringUTFChars(env, family_name_str, family_name); - pango_font_description_set_size (pfont->desc, size * dpi_conversion_factor); if (style & java_awt_font_BOLD) pango_font_description_set_weight (pfont->desc, PANGO_WEIGHT_BOLD); @@ -152,6 +362,7 @@ Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont if (useGraphics2D) { + pango_font_description_set_size (pfont->desc, size * PANGO_SCALE); if (pfont->ctx == NULL) { ft2_map = PANGO_FT2_FONT_MAP(pango_ft2_font_map_for_display ()); @@ -160,6 +371,9 @@ Java_gnu_java_awt_peer_gtk_GdkFontPeer_setFont } else { + /* GDK uses a slightly different DPI setting. */ + pango_font_description_set_size (pfont->desc, + size * dpi_conversion_factor); if (pfont->ctx == NULL) pfont->ctx = gdk_pango_context_get(); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c deleted file mode 100644 index df72097..0000000 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c +++ /dev/null @@ -1,696 +0,0 @@ -/* gdkglyphvector.c - Copyright (C) 2003, 2004 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. - - You should have received a copy of the GNU General Public License - along with GNU Classpath; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. - - Linking this library statically or dynamically with other modules is - making a combined work based on this library. Thus, the terms and - conditions of the GNU General Public License cover the whole - combination. - - As a special exception, the copyright holders of this library give you - permission to link this library with independent modules to produce an - executable, regardless of the license terms of these independent - modules, and to copy and distribute the resulting executable under - terms of your choice, provided that you also meet, for each linked - independent module, the terms and conditions of the license of that - module. An independent module is a module which is not derived from - or based on this library. If you modify this library, you may extend - this exception to your version of the library, but you are not - obligated to do so. If you do not wish to do so, delete this - exception statement from your version. */ - -#include "gdkfont.h" -#include "gnu_java_awt_peer_gtk_GdkGlyphVector.h" - -struct state_table *native_glyphvector_state_table; - -typedef struct { - double x; - double y; - double width; - double height; -} rect_t; - -#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) -#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) -#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) -#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0) - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_initStaticState - (JNIEnv *env, jclass clazz) -{ - NSA_GV_INIT (env, clazz); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_initState - (JNIEnv *env, jobject self, jobject font, jobject ctx __attribute__ ((unused))) -{ - struct glyphvec *vec = NULL; - struct peerfont *pfont = NULL; - - gdk_threads_enter (); - g_assert (font != NULL); - pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); - g_assert (pfont != NULL); - g_assert (pfont->ctx != NULL); - g_assert (pfont->desc != NULL); - - g_assert (self != NULL); - vec = (struct glyphvec *) g_malloc0 (sizeof (struct glyphvec)); - g_assert (vec != NULL); - - vec->desc = pango_font_describe (pfont->font); - g_assert (vec->desc != NULL); - - vec->font = pfont->font; - g_object_ref (vec->font); - - vec->ctx = pfont->ctx; - g_object_ref (vec->ctx); - - NSA_SET_GV_PTR (env, self, vec); - gdk_threads_leave (); -} - -static void free_glyphitems (GList *list) -{ - GList *i = NULL; - PangoGlyphItem *gi = NULL; - - for (i = g_list_first (list); i != NULL; i = g_list_next (i)) - { - g_assert (i->data != NULL); - gi = (PangoGlyphItem *)i->data; - - if (gi->glyphs != NULL) - pango_glyph_string_free (gi->glyphs); - - if (gi->item != NULL) - g_free (gi->item); - } - g_list_free (list); -} - -static void seek_glyphstring_idx (GList *list, int idx, - int *nidx, - PangoGlyphString **gs, - PangoFont **fnt) -{ - GList *i = NULL; - PangoGlyphItem *gi = NULL; - int begin = 0; - - g_assert (list != NULL); - g_assert (gs != NULL); - g_assert (nidx != NULL); - - - for (i = g_list_first (list); i != NULL; i = g_list_next (i)) - { - g_assert (i->data != NULL); - gi = (PangoGlyphItem *)i->data; - - g_assert (gi->glyphs != NULL); - - if (begin <= idx && idx < begin + gi->glyphs->num_glyphs) - { - *gs = gi->glyphs; - *nidx = idx - begin; - if (fnt && gi->item) - *fnt = gi->item->analysis.font; - return; - } - else - { - begin += gi->glyphs->num_glyphs; - } - } - *gs = NULL; - *nidx = -1; -} - -static void seek_glyph_idx (GList *list, int idx, - PangoGlyphInfo **g, - PangoFont **fnt) -{ - PangoGlyphString *gs = NULL; - int nidx = -1; - - g_assert (list != NULL); - g_assert (g != NULL); - - seek_glyphstring_idx (list, idx, &nidx, &gs, fnt); - - g_assert (gs != NULL); - g_assert (nidx != -1); - g_assert (nidx < gs->num_glyphs); - g_assert (gs->glyphs != NULL); - - *g = gs->glyphs + nidx; -} - -static void union_rects (rect_t *r1, - const rect_t *r2) -{ - rect_t r; - - g_assert (r1 != NULL); - g_assert (r2 != NULL); - - /* - x is the left edge of the rect, - y is the top edge of the rect - */ - -#ifndef min -#define min(x,y) ((x) < (y) ? (x) : (y)) -#endif - -#ifndef max -#define max(x,y) ((x) < (y) ? (y) : (x)) -#endif - - r.x = min(r1->x, r2->x); - - r.y = min(r1->y, r2->y); - - r.width = max(r1->x + r1->width, - r2->x + r2->width) - r.x; - - r.height = max(r1->y + r1->height, - r2->y + r2->height) - r.y; - - *r1 = r; -} - -static jdoubleArray rect_to_array (JNIEnv *env, const rect_t *r) -{ - /* We often return rectangles as arrays : { x, y, w, h } */ - jdoubleArray ret; - double *rp = NULL; - g_assert (r != NULL); - ret = (*env)->NewDoubleArray (env, 4); - rp = (*env)->GetDoubleArrayElements (env, ret, NULL); - g_assert (rp != NULL); - rp[0] = r->x; - /* freetype and pango's view of space is upside down from java2d's */ - rp[1] = r->y * -1; - rp[2] = r->width; - rp[3] = r->height; - (*env)->ReleaseDoubleArrayElements (env, ret, rp, 0); - return ret; -} - - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_dispose - (JNIEnv *env, jobject self) -{ - struct glyphvec *vec = NULL; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_DEL_GV_PTR (env, self); - g_assert (vec != NULL); - - if (vec->glyphitems != NULL) - { - free_glyphitems (vec->glyphitems); - vec->glyphitems = NULL; - } - - if (vec->desc != NULL) - pango_font_description_free (vec->desc); - - if (vec->ctx != NULL) - g_object_unref (vec->ctx); - - g_free (vec); - gdk_threads_leave (); -} - - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_setChars - (JNIEnv *env, jobject self, jstring chars) -{ - struct glyphvec *vec = NULL; - gchar *str = NULL; - GList *items = NULL, *item = NULL; - PangoGlyphItem *gi; - PangoAttrList *attrs = NULL; - gint len = 0; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - g_assert (vec != NULL); - g_assert (vec->desc != NULL); - g_assert (vec->ctx != NULL); - - len = (*gdk_env)->GetStringUTFLength (env, chars); - str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL); - g_assert (str != NULL); - - /* step 1: set our FontFescription in the context, then "itemize" the - text */ - - attrs = pango_attr_list_new (); - g_assert (attrs != NULL); - - pango_context_set_font_description (vec->ctx, vec->desc); - - if (vec->glyphitems != NULL) - items = pango_itemize (vec->ctx, str, 0, len, attrs, NULL); - if (items != NULL) - { - - /* - step 2: for each item: - - shape the item into a glyphstring - - store the (item, glyphstring) pair in the vec->glyphitems list - */ - - if (vec->glyphitems != NULL) - { - free_glyphitems (vec->glyphitems); - vec->glyphitems = NULL; - } - - for (item = g_list_first (items); - item != NULL; - item = g_list_next (item)) - { - g_assert (item->data != NULL); - - gi = NULL; - gi = g_malloc0 (sizeof(PangoGlyphItem)); - g_assert (gi != NULL); - - gi->item = (PangoItem *)item->data; - gi->glyphs = pango_glyph_string_new (); - g_assert (gi->glyphs != NULL); - - if (gi->glyphs->num_glyphs > 0) - { - pango_shape (str + gi->item->offset, - gi->item->length, - &(gi->item->analysis), - gi->glyphs); - - vec->glyphitems = g_list_append (vec->glyphitems, gi); - } - } - - /* - ownership of each item has been transferred to glyphitems, - but the list should be freed. - */ - - g_list_free (items); - } - - pango_attr_list_unref (attrs); - - (*env)->ReleaseStringUTFChars (env, chars, str); - gdk_threads_leave (); -} - - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_setGlyphCodes - (JNIEnv *env, jobject self, jintArray codes __attribute__ ((unused))) -{ - struct glyphvec *vec = NULL; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - g_assert (vec != NULL); - - /* - FIXME: setting glyph codes doesn't seem particularly plausible at the - moment. - */ - - gdk_threads_leave (); - -} - - -JNIEXPORT jint JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphCode - (JNIEnv *env, jobject self, jint idx) -{ - struct glyphvec *vec = NULL; - PangoGlyphInfo *gi = NULL; - jint ret = 0; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - g_assert (vec != NULL); - g_assert (vec->glyphitems != NULL); - - seek_glyph_idx (vec->glyphitems, idx, &gi, NULL); - g_assert (gi != NULL); - ret = gi->glyph; - gdk_threads_leave (); - - return (jint)(ret); -} - - -JNIEXPORT jint JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_numGlyphs - (JNIEnv *env, jobject self) -{ - GList *i = NULL; - PangoGlyphItem *gi = NULL; - struct glyphvec *vec = NULL; - jint count = 0; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - g_assert (vec != NULL); - - for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i)) - { - g_assert (i->data != NULL); - gi = (PangoGlyphItem *)i->data; - g_assert (gi->glyphs != NULL); - count += gi->glyphs->num_glyphs; - } - gdk_threads_leave (); - - return count; -} - - -JNIEXPORT jint JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphCharIndex -(JNIEnv *env __attribute__ ((unused)), jobject self __attribute__ ((unused)), jint idx) -{ - /* - FIXME: this is not correct, rather it assumes a (broken) 1:1 - glyph:char model. it can be implemented in terms of bytes (also - broken) using pango's current interface, or perhaps in terms of - characters if some better byte->character conversion operator is - found. for the time being we leave it broken. - */ - return idx; -} - -static void -assume_pointsize_and_identity_transform(double pointsize, - FT_Face face) -{ - FT_Matrix mat; - mat.xx = DOUBLE_TO_16_16(1); - mat.xy = DOUBLE_TO_16_16(0); - mat.yx = DOUBLE_TO_16_16(0); - mat.yy = DOUBLE_TO_16_16(1); - FT_Set_Transform(face, &mat, NULL); - FT_Set_Char_Size( face, - DOUBLE_TO_26_6 (pointsize), - DOUBLE_TO_26_6 (pointsize), - 0, 0); -} - -JNIEXPORT jdoubleArray JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allInkExtents - (JNIEnv *env, jobject self) -{ - struct glyphvec *vec = NULL; - int j; - GList *i; - PangoGlyphItem *gi = NULL; - rect_t rect = {0,0,0,0}; - rect_t tmp; - jdoubleArray ret; - double x = 0, y = 0; - double pointsize; - FT_Face face; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - g_assert (vec != NULL); - if (vec->glyphitems != NULL) - { - pointsize = pango_font_description_get_size (vec->desc); - pointsize /= (double) PANGO_SCALE; - - for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i)) - { - g_assert (i->data != NULL); - gi = (PangoGlyphItem *)i->data; - g_assert (gi->glyphs != NULL); - - face = pango_ft2_font_get_face (gi->item->analysis.font); - assume_pointsize_and_identity_transform (pointsize, face); - - for (j = 0; j < gi->glyphs->num_glyphs; ++j) - { - FT_Load_Glyph (face, - gi->glyphs->glyphs[j].glyph, - FT_LOAD_DEFAULT); - /* FIXME: this needs to change for vertical layouts */ - tmp.x = x + DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingX); - tmp.y = y + DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingY); - tmp.width = DOUBLE_FROM_26_6 (face->glyph->metrics.width); - tmp.height = DOUBLE_FROM_26_6 (face->glyph->metrics.height); - union_rects (&rect, &tmp); - x += DOUBLE_FROM_26_6 (face->glyph->advance.x); - y += DOUBLE_FROM_26_6 (face->glyph->advance.y); - } - } - } - - ret = rect_to_array (env, &rect); - gdk_threads_leave (); - return ret; -} - - -JNIEXPORT jdoubleArray JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allLogicalExtents - (JNIEnv *env, jobject self) -{ - struct glyphvec *vec = NULL; - int j; - GList *i; - PangoGlyphItem *gi = NULL; - rect_t rect = {0,0,0,0}; - rect_t tmp; - jdoubleArray ret; - double x = 0, y = 0; - double pointsize; - FT_Face face; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - g_assert (vec != NULL); - g_assert (vec->glyphitems != NULL); - - pointsize = pango_font_description_get_size (vec->desc); - pointsize /= (double) PANGO_SCALE; - - for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i)) - { - g_assert (i->data != NULL); - gi = (PangoGlyphItem *)i->data; - g_assert (gi->glyphs != NULL); - - face = pango_ft2_font_get_face (gi->item->analysis.font); - assume_pointsize_and_identity_transform (pointsize, face); - - for (j = 0; j < gi->glyphs->num_glyphs; ++j) - { - FT_Load_Glyph (face, gi->glyphs->glyphs[j].glyph, FT_LOAD_DEFAULT); - - /* FIXME: also, this is probably not the correct set of metrics; - the "logical bounds" are some fancy combination of hori - advance and height such that it's good for inverting as a - highlight. revisit. */ - - tmp.x = x; - tmp.y = y; - tmp.width = DOUBLE_FROM_26_6 (face->glyph->advance.x); - tmp.height = DOUBLE_FROM_26_6 (face->glyph->advance.y); - union_rects (&rect, &tmp); - x += DOUBLE_FROM_26_6 (face->glyph->advance.x); - y += DOUBLE_FROM_26_6 (face->glyph->advance.y); - } - } - - ret = rect_to_array (env, &rect); - gdk_threads_leave (); - return ret; -} - - -JNIEXPORT jdoubleArray JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphLogicalExtents - (JNIEnv *env, jobject self, jint idx) -{ - struct glyphvec *vec = NULL; - rect_t rect = {0,0,0,0}; - PangoGlyphInfo *gi = NULL; - PangoFont *font = NULL; - jdoubleArray ret; - double pointsize; - FT_Face face; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - g_assert (vec != NULL); - g_assert (vec->glyphitems != NULL); - - seek_glyph_idx (vec->glyphitems, idx, &gi, &font); - g_assert (gi != NULL); - g_assert (font != NULL); - - pointsize = pango_font_description_get_size (vec->desc); - pointsize /= (double) PANGO_SCALE; - face = pango_ft2_font_get_face (font); - - assume_pointsize_and_identity_transform (pointsize, face); - - FT_Load_Glyph (face, gi->glyph, FT_LOAD_DEFAULT); - - /* FIXME: this is probably not the correct set of metrics; - the "logical bounds" are some fancy combination of hori - advance and height such that it's good for inverting as a - highlight. revisit. */ - - rect.x = 0; - rect.y = 0; - rect.width = DOUBLE_FROM_26_6 (face->glyph->advance.x); - rect.height = DOUBLE_FROM_26_6 (face->glyph->advance.y); - - ret = rect_to_array (env, &rect); - gdk_threads_leave (); - return ret; -} - - -JNIEXPORT jdoubleArray JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphInkExtents - (JNIEnv *env, jobject self, jint idx) -{ - struct glyphvec *vec = NULL; - rect_t rect = {0,0,0,0}; - PangoGlyphInfo *gi = NULL; - PangoFont *font = NULL; - jdoubleArray ret; - double pointsize; - FT_Face face; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - g_assert (vec != NULL); - g_assert (vec->glyphitems != NULL); - - seek_glyph_idx (vec->glyphitems, idx, &gi, &font); - g_assert (gi != NULL); - g_assert (font != NULL); - - pointsize = pango_font_description_get_size (vec->desc); - pointsize /= (double) PANGO_SCALE; - face = pango_ft2_font_get_face (font); - - assume_pointsize_and_identity_transform (pointsize, face); - - FT_Load_Glyph (face, gi->glyph, FT_LOAD_DEFAULT); - /* FIXME: this needs to change for vertical layouts */ - rect.x = DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingX); - rect.y = DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingY); - rect.width = DOUBLE_FROM_26_6 (face->glyph->metrics.width); - rect.height = DOUBLE_FROM_26_6 (face->glyph->metrics.height); - - ret = rect_to_array (env, &rect); - gdk_threads_leave (); - return ret; -} - - -JNIEXPORT jboolean JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphIsHorizontal -(JNIEnv *env, jobject self, jint idx __attribute__ ((unused))) -{ - struct glyphvec *vec = NULL; - PangoDirection dir; - - gdk_threads_enter (); - g_assert (self != NULL); - vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - g_assert (vec != NULL); - g_assert (vec->desc != NULL); - g_assert (vec->ctx != NULL); - - /* - FIXME: this is an approximation; it's not clear to me whether - glyphs themselves are horizontal or vertical so much as the - writing system or writing context. pango thinks it's a context - issue, so we use that for now. - */ - - dir = pango_context_get_base_dir (vec->ctx); - - gdk_threads_leave (); - - return 1; - /* FIXME: Pango doesn't seem to have decided how it will deal - with vertical text. for the time being we inherit this limitation. - ((dir == PANGO_DIRECTION_LTR) || - (dir == PANGO_DIRECTION_RTL)); - */ -} - - -JNIEXPORT jboolean JNICALL -Java_gnu_java_awt_peer_gtk_GdkGlyphVector_isEqual - (JNIEnv *env, jobject self, jobject other) -{ - struct glyphvec *vec1 = NULL, *vec2 = NULL; - jboolean eq = 0; - - gdk_threads_enter (); - g_assert (self != NULL); - vec1 = (struct glyphvec *)NSA_GET_GV_PTR (env, self); - vec2 = (struct glyphvec *)NSA_GET_GV_PTR (env, other); - g_assert (vec1 != NULL); - g_assert (vec2 != NULL); - - /* FIXME: is there some more advantageous definition of equality for - glyph vectors? */ - eq = (vec1 == vec2); - - gdk_threads_leave (); - return eq; -} - - diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c index a91eea1..99b1511 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c @@ -133,13 +133,17 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics_connectSignals (JNIEnv *env, jobject obj, jobject peer) { void *ptr; + jobject *gref; + + NSA_SET_GLOBAL_REF (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); ptr = NSA_GET_PTR (env, peer); gdk_threads_enter (); g_signal_connect_after (G_OBJECT (ptr), "realize", - G_CALLBACK (realize_cb), obj); + G_CALLBACK (realize_cb), *gref); gdk_threads_leave (); } @@ -438,6 +442,12 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics_clearRect g = (struct graphics *) NSA_GET_PTR (env, obj); gdk_threads_enter (); + + if (!g) + { + gdk_threads_leave (); + return; + } if (GDK_IS_WINDOW (g->drawable)) { w.widget = &widget; @@ -455,6 +465,8 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics_clearRect x + g->x_offset, y + g->y_offset, width, height); gdk_gc_set_foreground (g->gc, &(saved.foreground)); } + + gdk_flush (); gdk_threads_leave (); } @@ -672,7 +684,9 @@ static void realize_cb (GtkWidget *widget __attribute__ ((unused)), { gdk_threads_leave (); - (*gdk_env)->CallVoidMethod (gdk_env, peer, initComponentGraphicsID); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, initComponentGraphicsID); + + NSA_DEL_GLOBAL_REF (gdk_env(), peer); gdk_threads_enter (); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c index 90b6aa1..e6535b4 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c @@ -1,5 +1,5 @@ /* gnu_java_awt_peer_gtk_GdkGraphics2d.c - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,7 +45,8 @@ #include <gdk-pixbuf/gdk-pixbuf.h> #include <gdk-pixbuf/gdk-pixdata.h> -#include <cairo.h> +#include <cairo-ft.h> +#include <cairo-xlib.h> #include <stdio.h> #include <stdlib.h> @@ -175,7 +176,6 @@ x_server_has_render_extension (void) return (int) XRenderQueryExtension (GDK_DISPLAY (), &ev, &err); } - static void init_graphics2d_as_pixbuf (struct graphics2d *gr) { @@ -196,13 +196,14 @@ init_graphics2d_as_pixbuf (struct graphics2d *gr) g_assert (gdk_pixbuf_get_bits_per_sample (gr->drawbuf) == bits_per_sample); g_assert (gdk_pixbuf_get_n_channels (gr->drawbuf) == total_channels); - gr->surface = cairo_surface_create_for_image (gdk_pixbuf_get_pixels (gr->drawbuf), + gr->surface = cairo_surface_create_for_image ((char *) gdk_pixbuf_get_pixels (gr->drawbuf), CAIRO_FORMAT_ARGB32, gdk_pixbuf_get_width (gr->drawbuf), gdk_pixbuf_get_height (gr->drawbuf), gdk_pixbuf_get_rowstride (gr->drawbuf)); g_assert (gr->surface != NULL); g_assert (gr->cr != NULL); + gr->mode = MODE_DRAWABLE_NO_RENDER; cairo_set_target_surface (gr->cr, gr->surface); } @@ -232,60 +233,99 @@ init_graphics2d_as_renderable (struct graphics2d *gr) DefaultColormap (dpy, DefaultScreen (dpy))); g_assert (gr->surface != NULL); g_assert (gr->cr != NULL); + gr->mode = MODE_DRAWABLE_WITH_RENDER; cairo_set_target_surface (gr->cr, gr->surface); } static void -begin_drawing_operation (struct graphics2d * gr) +begin_drawing_operation (JNIEnv *env, struct graphics2d * gr) { g_assert(cairo_status (gr->cr) == CAIRO_STATUS_SUCCESS); - if (gr->drawbuf) + + switch (gr->mode) { + case MODE_DRAWABLE_WITH_RENDER: + break; - gint drawable_width, drawable_height; - gint pixbuf_width, pixbuf_height; - gint width, height; - - gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); - pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); - pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); - width = min (drawable_width, pixbuf_width); - height = min (drawable_height, pixbuf_height); - - gdk_pixbuf_get_from_drawable (gr->drawbuf, /* destination pixbuf */ - gr->drawable, - NULL, /* colormap */ - 0, 0, 0, 0, - width, height); - - if (gr->debug) printf ("copied (%d, %d) pixels from GDK drawable to pixbuf\n", - width, height); + case MODE_DRAWABLE_NO_RENDER: + { + + gint drawable_width, drawable_height; + gint pixbuf_width, pixbuf_height; + gint width, height; + + gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); + pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); + pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); + width = min (drawable_width, pixbuf_width); + height = min (drawable_height, pixbuf_height); + + gdk_pixbuf_get_from_drawable (gr->drawbuf, /* destination pixbuf */ + gr->drawable, + NULL, /* colormap */ + 0, 0, 0, 0, + width, height); + + if (gr->debug) printf ("copied (%d, %d) pixels from GDK drawable to pixbuf\n", + width, height); + } + break; + + case MODE_JAVA_ARRAY: + gr->javabuf = (*env)->GetIntArrayElements (env, gr->jarray, &gr->isCopy); + gr->surface = cairo_surface_create_for_image ((char *) gr->javabuf, + CAIRO_FORMAT_ARGB32, + gr->width, + gr->height, + gr->width * 4); + g_assert(gr->surface != NULL); + g_assert(gr->cr != NULL); + cairo_set_target_surface (gr->cr, gr->surface); + break; } } static void -end_drawing_operation (struct graphics2d * gr) +end_drawing_operation (JNIEnv *env, struct graphics2d * gr) { g_assert(cairo_status (gr->cr) == CAIRO_STATUS_SUCCESS); - if (gr->drawbuf) - { - gint drawable_width, drawable_height; - gint pixbuf_width, pixbuf_height; - gint width, height; + + switch (gr->mode) + { + case MODE_DRAWABLE_WITH_RENDER: + break; + + case MODE_DRAWABLE_NO_RENDER: + { + + gint drawable_width, drawable_height; + gint pixbuf_width, pixbuf_height; + gint width, height; + + gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); + pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); + pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); + width = min (drawable_width, pixbuf_width); + height = min (drawable_height, pixbuf_height); + + gdk_draw_pixbuf (gr->drawable, NULL, gr->drawbuf, + 0, 0, 0, 0, + width, height, + GDK_RGB_DITHER_NORMAL, 0, 0); + + if (gr->debug) printf ("copied (%d, %d) pixels from pixbuf to GDK drawable\n", + width, height); + } + break; - gdk_drawable_get_size (gr->drawable, &drawable_width, &drawable_height); - pixbuf_width = gdk_pixbuf_get_width (gr->drawbuf); - pixbuf_height = gdk_pixbuf_get_height (gr->drawbuf); - width = min (drawable_width, pixbuf_width); - height = min (drawable_height, pixbuf_height); - - gdk_draw_pixbuf (gr->drawable, NULL, gr->drawbuf, - 0, 0, 0, 0, - width, height, - GDK_RGB_DITHER_NORMAL, 0, 0); - - if (gr->debug) printf ("copied (%d, %d) pixels from pixbuf to GDK drawable\n", - width, height); + case MODE_JAVA_ARRAY: + /* + * FIXME: Perhaps this should use the isCopy flag to try to avoid + * tearing down the cairo surface. + */ + cairo_surface_destroy (gr->surface); + gr->surface = NULL; + (*env)->ReleaseIntArrayElements (env, gr->jarray, gr->javabuf, JNI_COMMIT); } } @@ -317,11 +357,11 @@ check_for_debug (struct graphics2d *gr) } static void -realize_cb (GtkWidget *widget, jobject peer) +realize_cb (GtkWidget *widget __attribute__ ((unused)), jobject peer) { gdk_threads_leave (); - (*gdk_env)->CallVoidMethod (gdk_env, peer, initComponentGraphics2DID); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, initComponentGraphics2DID); gdk_threads_enter (); } @@ -342,18 +382,29 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState if (g_old->debug) printf ("copying state from existing graphics2d\n"); - g->drawable = g_old->drawable; g->debug = g_old->debug; + g->mode = g_old->mode; - g_object_ref (g->drawable); + if (g_old->mode == MODE_JAVA_ARRAY) + { + g->width = g_old->width; + g->height = g_old->height; + g->jarray = (*env)->NewGlobalRef(env, g_old->jarray); + } + else + { + g->drawable = g_old->drawable; + + g_object_ref (g->drawable); - g->cr = cairo_create(); - g_assert (g->cr != NULL); + g->cr = cairo_create(); + g_assert (g->cr != NULL); - if (x_server_has_render_extension ()) - init_graphics2d_as_renderable (g); - else - init_graphics2d_as_pixbuf (g); + if (x_server_has_render_extension ()) + init_graphics2d_as_renderable (g); + else + init_graphics2d_as_pixbuf (g); + } cairo_surface_set_filter (g->surface, CAIRO_FILTER_FAST); @@ -363,6 +414,37 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_copyState JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState___3III +(JNIEnv *env, jobject obj, jintArray jarr, jint width, jint height) +{ + struct graphics2d *gr; + + gdk_threads_enter(); + gr = (struct graphics2d *) malloc (sizeof (struct graphics2d)); + g_assert (gr != NULL); + memset (gr, 0, sizeof(struct graphics2d)); + + check_for_debug (gr); + + if (gr->debug) printf ("constructing java-backed image of size (%d,%d)\n", + width, height); + + gr->cr = cairo_create(); + g_assert (gr->cr != NULL); + + gr->width = width; + gr->height = height; + gr->jarray = (*env)->NewGlobalRef(env, jarr); + gr->mode = MODE_JAVA_ARRAY; + + if (gr->debug) printf ("constructed java-backed image of size (%d,%d)\n", + width, height); + + NSA_SET_G2D_PTR (env, obj, gr); + gdk_threads_leave(); +} + +JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_initState__II (JNIEnv *env, jobject obj, jint width, jint height) { @@ -414,7 +496,7 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable if (src->debug) printf ("copying from offscreen drawable\n"); - begin_drawing_operation(dst); + begin_drawing_operation(env, dst); /* gdk_flush(); */ @@ -439,7 +521,7 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable gdk_flush(); - end_drawing_operation(dst); + end_drawing_operation(env, dst); if (src->debug) printf ("copied %d x %d pixels from offscreen drawable\n", width, height); gdk_threads_leave(); @@ -531,6 +613,9 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose if (gr->pattern_pixels) free (gr->pattern_pixels); + if (gr->mode == MODE_JAVA_ARRAY) + (*env)->DeleteGlobalRef(env, gr->jarray); + if (gr->debug) printf ("disposed of graphics2d\n"); free (gr); @@ -734,7 +819,7 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels g_assert (native_matrix != NULL); g_assert ((*env)->GetArrayLength (env, java_matrix) == 6); - begin_drawing_operation (gr); + begin_drawing_operation (env, gr); { cairo_matrix_t *mat = NULL; @@ -748,13 +833,12 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels native_matrix[4], native_matrix[5]); cairo_surface_set_matrix (surf, mat); cairo_surface_set_filter (surf, cairo_surface_get_filter(gr->surface)); - cairo_show_surface (gr->cr, surf, w, h); cairo_matrix_destroy (mat); cairo_surface_destroy (surf); } - end_drawing_operation (gr); + end_drawing_operation (env, gr); (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0); (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0); @@ -762,65 +846,6 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels gdk_threads_leave(); } -JNIEXPORT jintArray JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_getImagePixels - (JNIEnv *env, jobject obj) -{ - struct graphics2d *gr = NULL; - jintArray java_pixels; - jint* native_pixels; - GdkPixbuf *buf = NULL; - gint width, height; - gint bits_per_sample = 8; - gboolean has_alpha = TRUE; - gint total_channels = 4; - jint i; - - gdk_threads_enter(); - if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return NULL; } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert (gr != NULL); - - if (gr->debug) printf ("getImagePixels\n"); - - gdk_drawable_get_size (gr->drawable, &width, &height); - - buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, - bits_per_sample, - width, height); - g_assert (buf != NULL); - g_assert (gdk_pixbuf_get_bits_per_sample (buf) == bits_per_sample); - g_assert (gdk_pixbuf_get_n_channels (buf) == total_channels); - - - /* copy pixels from drawable to pixbuf */ - - gdk_pixbuf_get_from_drawable (buf, gr->drawable, - NULL, - 0, 0, 0, 0, - width, height); - - native_pixels= gdk_pixbuf_get_pixels (buf); - -#ifndef WORDS_BIGENDIAN - /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */ - for (i=0; i<width * height; i++) - { - native_pixels[i] = SWAPU32 ((unsigned)native_pixels[i]); - } -#endif - - java_pixels = (*env) -> NewIntArray (env, width * height); - - (*env)->SetIntArrayRegion(env, java_pixels, - (jsize)0, (jsize) width*height, - (jint*) native_pixels); - - gdk_threads_leave(); - return java_pixels; -} - /* passthrough methods to cairo */ JNIEXPORT void JNICALL @@ -917,13 +942,13 @@ install_font_peer(cairo_t *cr, if (debug) printf ("install_font_peer made new cairo font for '%s' at %f\n", face->family_name, (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE) * (96.0 / 72.0)); + (double)PANGO_SCALE)); cairo_set_font (cr, ft); cairo_font_destroy (ft); cairo_scale_font (cr, (pango_font_description_get_size (pfont->desc) / - (double)PANGO_SCALE) * (96.0 / 72.0)); + (double)PANGO_SCALE)); ft = cairo_current_font (cr); pfont->graphics_resource = ft; } @@ -935,24 +960,10 @@ install_font_peer(cairo_t *cr, } } -static cairo_t *metrics_cairo = NULL; -static cairo_surface_t *metrics_surface = NULL; - -static void -ensure_metrics_cairo() -{ - if (metrics_cairo == NULL) - { - metrics_cairo = cairo_create (); - metrics_surface = cairo_image_surface_create (CAIRO_FORMAT_A8, 1, 1); - cairo_set_target_surface (metrics_cairo, metrics_surface); - } -} - JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_releasePeerGraphicsResource - (JNIEnv *env, jclass clazz, jobject java_font) + (JNIEnv *env, jclass clazz __attribute__ ((unused)), jobject java_font) { struct peerfont *pfont = NULL; @@ -969,80 +980,9 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_releasePeerGraphicsResource gdk_threads_leave(); } -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_getPeerTextMetrics - (JNIEnv *env, jclass clazz, jobject java_font, jstring str, jdoubleArray java_metrics) -{ - struct peerfont *pfont = NULL; - const char *cstr = NULL; - jdouble *native_metrics = NULL; - cairo_text_extents_t extents; - - g_assert(java_font != NULL); - gdk_threads_enter(); - - pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, java_font); - g_assert (pfont != NULL); - - ensure_metrics_cairo(); - install_font_peer (metrics_cairo, pfont, 0); - - cstr = (*env)->GetStringUTFChars (env, str, NULL); - g_assert(cstr != NULL); - cairo_text_extents (metrics_cairo, cstr, &extents); - - native_metrics = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); - g_assert (native_metrics != NULL); - - native_metrics[TEXT_METRICS_X_BEARING] = extents.x_bearing; - native_metrics[TEXT_METRICS_Y_BEARING] = extents.y_bearing; - native_metrics[TEXT_METRICS_WIDTH] = extents.width; - native_metrics[TEXT_METRICS_HEIGHT] = extents.height; - native_metrics[TEXT_METRICS_X_ADVANCE] = extents.x_advance; - native_metrics[TEXT_METRICS_Y_ADVANCE] = extents.y_advance; - - (*env)->ReleaseStringUTFChars (env, str, cstr); - (*env)->ReleaseDoubleArrayElements (env, java_metrics, native_metrics, 0); - gdk_threads_leave(); -} - -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_getPeerFontMetrics - (JNIEnv *env, jclass clazz, jobject java_font, jdoubleArray java_metrics) -{ - struct peerfont *pfont = NULL; - jdouble *native_metrics = NULL; - cairo_font_extents_t extents; - - g_assert(java_font != NULL); - - gdk_threads_enter(); - - pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, java_font); - g_assert (pfont != NULL); - - ensure_metrics_cairo(); - install_font_peer (metrics_cairo, pfont, 0); - - cairo_current_font_extents (metrics_cairo, &extents); - - native_metrics = (*env)->GetDoubleArrayElements (env, java_metrics, NULL); - g_assert (native_metrics != NULL); - - native_metrics[FONT_METRICS_ASCENT] = extents.ascent; - native_metrics[FONT_METRICS_MAX_ASCENT] = extents.ascent; - native_metrics[FONT_METRICS_DESCENT] = extents.descent; - if (native_metrics[FONT_METRICS_DESCENT] < 0) - native_metrics[FONT_METRICS_DESCENT] = - native_metrics[FONT_METRICS_DESCENT]; - native_metrics[FONT_METRICS_MAX_DESCENT] = native_metrics[FONT_METRICS_DESCENT]; - native_metrics[FONT_METRICS_MAX_ADVANCE] = extents.max_x_advance; - - (*env)->ReleaseDoubleArrayElements (env, java_metrics, native_metrics, 0); - gdk_threads_leave(); -} - static void -paint_glyph_run(struct graphics2d *gr, +paint_glyph_run(JNIEnv *env, + struct graphics2d *gr, cairo_glyph_t **glyphs, gint *n_glyphs, PangoLayoutRun *run) @@ -1090,134 +1030,71 @@ paint_glyph_run(struct graphics2d *gr, } if (gr->debug) printf("\n"); - begin_drawing_operation (gr); + begin_drawing_operation (env, gr); cairo_show_glyphs (gr->cr, *glyphs, run->glyphs->num_glyphs); - end_drawing_operation (gr); + end_drawing_operation (env, gr); } } -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawString - (JNIEnv *env, jobject obj, jobject font, jstring str, float x, float y) -{ - struct graphics2d *gr = NULL; - const char *cstr = NULL; - struct peerfont *pfont = NULL; - - /* - cairo_glyph_t *glyphs = NULL; - gint n_glyphs = 0; - PangoLayoutRun *run = NULL; - PangoLayoutIter *iter = NULL; - */ - - g_assert(obj != NULL); - g_assert(font != NULL); - g_assert(str != NULL); - - gdk_threads_enter (); - if (peer_is_disposed(env, obj)) { gdk_threads_leave(); return; } - - gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); - g_assert(gr != NULL); - - pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, font); - g_assert (pfont != NULL); - - cstr = (*env)->GetStringUTFChars (env, str, NULL); - g_assert(cstr != NULL); - - if (gr->debug) printf ("painting string '%s' at (%f,%f)\n", cstr, x, y); - - /* For now we let cairo do the glyph conversion; eventually this - * ought to be unified with pango, but it is impossible to get - * pango and cairo to agree on metrics at the moment, so we either - * have to use "all cairo" metrics (the string-based APIs) or - * "all pango" metrics (the glyph-vector based APIs). - */ - - install_font_peer (gr->cr, pfont, gr->debug); - cairo_move_to (gr->cr, x, y); - cairo_show_text (gr->cr, cstr); - - /* - - pango_layout_set_text (gr->pango_layout, cstr, -1); - - iter = pango_layout_get_iter (gr->pango_layout); - g_assert(iter != NULL); - - cairo_translate (gr->cr, x, y); - - do - { - run = pango_layout_iter_get_run (iter); - if (run != NULL) - paint_glyph_run (gr, &glyphs, &n_glyphs, run); - } - while (pango_layout_iter_next_run (iter)); - - if (glyphs != NULL) - g_free (glyphs); - - cairo_translate (gr->cr, -x, -y); - - pango_layout_iter_free (iter); - - */ - - gdk_threads_leave (); - - (*env)->ReleaseStringUTFChars (env, str, cstr); -} - JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGdkGlyphVector - (JNIEnv *env, jobject self, jobject font, jobject java_vec, jfloat x, jfloat y) +Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGlyphVector + (JNIEnv *env, jobject self, + jobject font, + jfloat x, jfloat y, jint n, + jintArray java_codes, + jfloatArray java_positions) { struct graphics2d *gr = NULL; struct peerfont *pfont = NULL; - struct glyphvec *gv = NULL; - PangoLayoutRun *run = NULL; cairo_glyph_t *glyphs = NULL; - gint n_glyphs = 0; + int *native_codes; + float *native_positions; + jint i = 0; g_assert (self != NULL); - g_assert (java_vec != NULL); + g_assert (java_codes != NULL); + g_assert (java_positions != NULL); gdk_threads_enter (); if (peer_is_disposed(env, self)) { gdk_threads_leave(); return; } gr = (struct graphics2d *)NSA_GET_G2D_PTR (env, self); - gv = (struct glyphvec *)NSA_GET_GV_PTR (env, java_vec); - pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, font); - g_assert (gr != NULL); - g_assert (gv != NULL); + + pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font); g_assert (pfont != NULL); - if (gr->debug) printf ("painting pango glyph vector\n"); + install_font_peer(gr->cr, pfont, gr->debug); - install_font_peer (gr->cr, pfont, gr->debug); - cairo_translate (gr->cr, x, y); + glyphs = malloc( sizeof(cairo_glyph_t) * n); + g_assert (glyphs != NULL); - /* nb. PangoLayoutRun is a typedef for PangoGlyphItem. */ - run = (PangoLayoutRun *) gv->glyphitems; - if (run != NULL) - paint_glyph_run (gr, &glyphs, &n_glyphs, run); + native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL); + native_positions = (*env)->GetFloatArrayElements (env, java_positions, NULL); + + for (i = 0; i < n; ++i) + { + glyphs[i].index = native_codes[i]; + glyphs[i].x = x + native_positions[ 2*i ]; + glyphs[i].y = y + native_positions[ 2*i + 1]; + } - if (glyphs != NULL) - g_free (glyphs); + (*env)->ReleaseFloatArrayElements (env, java_positions, native_positions, 0); + (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0); + + begin_drawing_operation (env, gr); + cairo_show_glyphs (gr->cr, glyphs, n); + end_drawing_operation (env, gr); - cairo_translate (gr->cr, -x, -y); gdk_threads_leave (); + free(glyphs); } JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGdkTextLayout - (JNIEnv *env, jobject self, jobject font, jobject java_layout, jfloat x, jfloat y) + (JNIEnv *env, jobject self, jobject java_layout, jfloat x, jfloat y) { /* * FIXME: Some day we expect either cairo or pango will know how to make @@ -1225,7 +1102,6 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGdkTextLayout */ struct graphics2d *gr = NULL; - struct peerfont *pfont = NULL; struct textlayout *tl = NULL; PangoLayoutIter *i = NULL; PangoLayoutRun *run = NULL; @@ -1237,12 +1113,10 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGdkTextLayout gr = (struct graphics2d *)NSA_GET_G2D_PTR (env, self); tl = (struct textlayout *)NSA_GET_TEXT_LAYOUT_PTR (env, java_layout); - pfont = (struct peerfont *) NSA_GET_FONT_PTR (env, font); g_assert (gr != NULL); g_assert (tl != NULL); g_assert (tl->pango_layout != NULL); - g_assert (pfont != NULL); if (gr->debug) printf ("painting pango layout\n"); @@ -1252,14 +1126,13 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoDrawGdkTextLayout i = pango_layout_get_iter (tl->pango_layout); g_assert (i != NULL); - install_font_peer (gr->cr, pfont, gr->debug); cairo_translate (gr->cr, x, y); do { run = pango_layout_iter_get_run (i); if (run != NULL) - paint_glyph_run (gr, &glyphs, &n_glyphs, run); + paint_glyph_run (env, gr, &glyphs, &n_glyphs, run); } while (pango_layout_iter_next_run (i)); @@ -1671,9 +1544,9 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoStroke gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_stroke\n"); - begin_drawing_operation (gr); + begin_drawing_operation (env, gr); cairo_stroke (gr->cr); - end_drawing_operation (gr); + end_drawing_operation (env, gr); gdk_threads_leave(); } @@ -1689,9 +1562,9 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoFill gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); g_assert (gr != NULL); if (gr->debug) printf ("cairo_fill\n"); - begin_drawing_operation (gr); + begin_drawing_operation (env, gr); cairo_fill (gr->cr); - end_drawing_operation (gr); + end_drawing_operation (env, gr); gdk_threads_leave(); } @@ -1707,10 +1580,10 @@ Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoClip gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj); if (gr == NULL) { gdk_threads_leave (); return; } if (gr->debug) printf ("cairo_clip\n"); - begin_drawing_operation (gr); + begin_drawing_operation (env, gr); cairo_init_clip (gr->cr); cairo_clip (gr->cr); - end_drawing_operation (gr); + end_drawing_operation (env, gr); gdk_threads_leave(); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c index 3cb3bd2..0727999 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c @@ -60,6 +60,8 @@ static JavaVM *vm; static jmethodID areaPreparedID; static jmethodID areaUpdatedID; +static jmethodID dataOutputWriteID; +static jmethodID registerFormatID; static void area_prepared (GdkPixbufLoader *loader, @@ -193,10 +195,72 @@ Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initState NSA_SET_PB_PTR (env, obj, loader); } +static void +query_formats (JNIEnv *env, jclass clazz) +{ + jobject jformat; + GSList *formats, *f; + GdkPixbufFormat *format; + char **ch, *name; + + jclass formatClass; + jmethodID addExtensionID; + jmethodID addMimeTypeID; + + formatClass = (*env)->FindClass + (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec"); + + g_assert(formatClass != NULL); + + addExtensionID = (*env)->GetMethodID (env, formatClass, + "addExtension", + "(Ljava/lang/String;)V"); + + addMimeTypeID = (*env)->GetMethodID (env, formatClass, + "addMimeType", + "(Ljava/lang/String;)V"); + + formats = gdk_pixbuf_get_formats (); + + for (f = formats; f; f = f->next) + { + format = (GdkPixbufFormat *) f->data; + name = gdk_pixbuf_format_get_name(format); + + jformat = (*env)->CallStaticObjectMethod + (env, clazz, registerFormatID, + (*env)->NewStringUTF(env, name), + (jboolean) gdk_pixbuf_format_is_writable(format)); + + g_assert(jformat != NULL); + + ch = gdk_pixbuf_format_get_extensions(format); + while (*ch) + { + (*env)->CallVoidMethod (env, jformat, addExtensionID, + (*env)->NewStringUTF(env, *ch)); + ++ch; + } + + ch = gdk_pixbuf_format_get_mime_types(format); + while (*ch) + { + (*env)->CallVoidMethod (env, jformat, addMimeTypeID, + (*env)->NewStringUTF(env, *ch)); + ++ch; + } + } + + g_slist_free(formats); +} + + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState (JNIEnv *env, jclass clazz) { + jclass dataOutputClass; + (*env)->GetJavaVM(env, &vm); areaPreparedID = (*env)->GetMethodID (env, clazz, @@ -206,6 +270,20 @@ Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState areaUpdatedID = (*env)->GetMethodID (env, clazz, "areaUpdated", "(IIII[II)V"); + + registerFormatID = (*env)->GetStaticMethodID + (env, clazz, + "registerFormat", + "(Ljava/lang/String;Z)" + "Lgnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec;"); + + + dataOutputClass = (*env)->FindClass(env, "java/io/DataOutput"); + dataOutputWriteID = (*env)->GetMethodID (env, dataOutputClass, + "write", "([B)V"); + + query_formats (env, clazz); + NSA_PB_INIT (env, clazz); } @@ -226,6 +304,115 @@ Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_finish gdk_threads_leave (); } +struct stream_save_request +{ + JNIEnv *env; + jobject *stream; +}; + +static gboolean +save_to_stream(const gchar *buf, + gsize count, + GError **error __attribute__((unused)), + gpointer data) +{ + struct stream_save_request *ssr = (struct stream_save_request *)data; + + jbyteArray jbuf; + jbyte *cbuf; + + gdk_threads_leave (); + jbuf = (*(ssr->env))->NewByteArray ((ssr->env), count); + cbuf = (*(ssr->env))->GetByteArrayElements ((ssr->env), jbuf, NULL); + memcpy (cbuf, buf, count); + (*(ssr->env))->ReleaseByteArrayElements ((ssr->env), jbuf, cbuf, 0); + (*(ssr->env))->CallVoidMethod ((ssr->env), *(ssr->stream), + dataOutputWriteID, jbuf); + gdk_threads_enter (); + return TRUE; +} + + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_streamImage +(JNIEnv *env, jclass clazz __attribute__((unused)), + jintArray jarr, jstring jenctype, jint width, jint height, + jboolean hasAlpha, jobject stream) +{ + GdkPixbuf* pixbuf; + jint *ints; + guchar a, r, g, b, *pix, *p; + GError *err = NULL; + const char *enctype; + int i; + + struct stream_save_request ssr; + ssr.stream = &stream; + ssr.env = env; + + ints = (*env)->GetIntArrayElements (env, jarr, NULL); + pix = g_malloc(width * height * (hasAlpha ? 4 : 3)); + + enctype = (*env)->GetStringUTFChars (env, jenctype, NULL); + g_assert(enctype != NULL); + + g_assert (pix != NULL); + g_assert (ints != NULL); + + p = pix; + for (i = 0; i < width*height; ++i) + { + /* + * Java encodes pixels as integers in a predictable arithmetic order: + * 0xAARRGGBB. Since these are jints, JNI has already byte-swapped + * them for us if necessary, so they're in "our" endianness, whatever + * that is. It uses 4 bytes per pixel whether or not there's an alpha + * channel. + */ + + a = 0xff & (ints[i] >> 24); + r = 0xff & (ints[i] >> 16); + g = 0xff & (ints[i] >> 8); + b = 0xff & ints[i]; + + /* + * GDK-pixbuf has a very different storage model: + * + * - A different alpha order (alpha after colors). + * - A different packing model (no alpha -> 3-bytes-per-pixel). + * - A different "RGB" order (host memory order, not endian-neutral). + */ + + *p++ = r; + *p++ = g; + *p++ = b; + if (hasAlpha) + *p++ = a; + } + + gdk_threads_enter (); + pixbuf = gdk_pixbuf_new_from_data (pix, + GDK_COLORSPACE_RGB, + (gboolean) hasAlpha, + 8, width, height, + width * (hasAlpha ? 4 : 3), /* rowstride */ + NULL, NULL); + g_assert (pixbuf != NULL); + + g_assert(gdk_pixbuf_save_to_callback (pixbuf, + &save_to_stream, + &ssr, + enctype, + &err, NULL)); + + g_object_unref (pixbuf); + + gdk_threads_leave (); + g_free(pix); + + (*env)->ReleaseStringUTFChars (env, jenctype, enctype); + (*env)->ReleaseIntArrayElements (env, jarr, ints, 0); +} JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c new file mode 100644 index 0000000..6b1b4a9 --- /dev/null +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c @@ -0,0 +1,328 @@ +/* gdkrobotpeer.c + Copyright (C) 2004 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. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include "gtkpeer.h" +#include "gnu_java_awt_peer_gtk_GdkRobotPeer.h" +#include <gdk/gdkx.h> +#include <X11/extensions/XTest.h> + +static int +awt_button_mask_to_num (int buttons) +{ + switch (buttons) + { + case AWT_BUTTON1_MASK: + return 1; + case AWT_BUTTON2_MASK: + return 2; + case AWT_BUTTON3_MASK: + return 3; + } + + return 0; +} + +JNIEXPORT jboolean JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_initXTest + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) +{ + GdkDisplay *display; + Display *xdisplay; + int event_basep; + int error_basep; + int majorp; + int minorp; + jboolean result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + result = XTestQueryExtension (xdisplay, + &event_basep, + &error_basep, + &majorp, + &minorp); + + gdk_threads_leave (); + + return result; +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mouseMove + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint x, jint y) +{ + GdkDisplay *display; + Display *xdisplay; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + result = XTestFakeMotionEvent (xdisplay, + -1, + x, y, CurrentTime); + + XFlush (xdisplay); + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mousePress + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint buttons) +{ + GdkDisplay *display; + Display *xdisplay; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + result = XTestFakeButtonEvent (xdisplay, + awt_button_mask_to_num (buttons), + True, CurrentTime); + + XFlush (xdisplay); + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mouseRelease + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint buttons) +{ + GdkDisplay *display; + Display *xdisplay; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + result = XTestFakeButtonEvent (xdisplay, + awt_button_mask_to_num (buttons), + False, CurrentTime); + + XFlush (xdisplay); + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mouseWheel + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint wheelAmt) +{ + GdkDisplay *display; + Display *xdisplay; + int i = 0; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + if (wheelAmt < 0) + for (i = 0; i < -wheelAmt; i++) + { + XTestFakeButtonEvent (xdisplay, + 4, + True, CurrentTime); + XTestFakeButtonEvent (xdisplay, + 4, + False, CurrentTime); + } + else + for (i = 0; i < wheelAmt; i++) + { + XTestFakeButtonEvent (xdisplay, + 5, + True, CurrentTime); + XTestFakeButtonEvent (xdisplay, + 5, + False, CurrentTime); + } + + XFlush (xdisplay); + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_keyPress + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint keycode) +{ + GdkDisplay *display; + Display *xdisplay; + GdkKeymapKey *keymap_keys = NULL; + gint n_keys = 0; + guint lookup_keyval = 0; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + lookup_keyval = awt_keycode_to_keysym (keycode, AWT_KEY_LOCATION_LEFT); + + if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), + lookup_keyval, + &keymap_keys, + &n_keys)) + { + /* No matching keymap entry was found. */ + g_printerr ("No matching keymap entries were found\n"); + gdk_threads_leave (); + return; + } + + /* If n_keys > 1 then there are multiple hardware keycodes that + translate to lookup_keyval. We arbitrarily choose the first + hardware keycode from the list returned by + gdk_keymap_get_entries_for_keyval. */ + result = XTestFakeKeyEvent (xdisplay, + keymap_keys[0].keycode, + True, CurrentTime); + + g_free (keymap_keys); + + XFlush (xdisplay); + gdk_threads_leave (); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_keyRelease + (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)), jint keycode) +{ + GdkDisplay *display; + Display *xdisplay; + GdkKeymapKey *keymap_keys = NULL; + gint n_keys = 0; + guint lookup_keyval = 0; + int result; + + gdk_threads_enter (); + + display = gdk_display_get_default (); + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + lookup_keyval = awt_keycode_to_keysym (keycode, AWT_KEY_LOCATION_LEFT); + + if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), + lookup_keyval, + &keymap_keys, + &n_keys)) + { + /* No matching keymap entry was found. */ + g_printerr ("No matching keymap entries were found\n"); + gdk_threads_leave (); + return; + } + + /* If n_keys > 1 then there are multiple hardware keycodes that + translate to lookup_keyval. We arbitrarily choose the first + hardware keycode from the list returned by + gdk_keymap_get_entries_for_keyval. */ + result = XTestFakeKeyEvent (xdisplay, + keymap_keys[0].keycode, + False, CurrentTime); + + g_free (keymap_keys); + + XFlush (xdisplay); + gdk_threads_leave (); +} + +JNIEXPORT jintArray JNICALL +Java_gnu_java_awt_peer_gtk_GdkRobotPeer_nativeGetRGBPixels + (JNIEnv *env, jobject obj __attribute__((unused)), jint x, jint y, + jint width, jint height) +{ + jint stride_bytes, stride_pixels, n_channels, n_pixels; + jintArray jpixels; + jint *java_pixels; + guchar *gdk_pixels; + GdkPixbuf *pixbuf_no_alpha = NULL; + GdkPixbuf *pixbuf = NULL; + +#ifndef WORDS_BIGENDIAN + int i; +#endif + + gdk_threads_enter (); + + pixbuf_no_alpha = gdk_pixbuf_get_from_drawable (NULL, + gdk_get_default_root_window (), + NULL, x, y, 0, 0, + width, height); + + pixbuf = gdk_pixbuf_add_alpha(pixbuf_no_alpha, FALSE, 0, 0, 0); + g_assert (gdk_pixbuf_get_has_alpha (pixbuf)); + + stride_bytes = gdk_pixbuf_get_rowstride (pixbuf); + n_channels = gdk_pixbuf_get_n_channels (pixbuf); + stride_pixels = stride_bytes / n_channels; + n_pixels = height * stride_pixels; + gdk_pixels = gdk_pixbuf_get_pixels (pixbuf); + + jpixels = (*env)->NewIntArray (env, n_pixels); + java_pixels = (*env)->GetIntArrayElements (env, jpixels, NULL); + + memcpy (java_pixels, + gdk_pixels, + (height * stride_bytes)); + +#ifndef WORDS_BIGENDIAN + /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */ + for (i = 0; i < n_pixels; ++i) + { + java_pixels[i] = SWAPU32 ((unsigned)java_pixels[i]); + } +#endif + + g_object_unref (pixbuf); + + (*env)->ReleaseIntArrayElements (env, jpixels, java_pixels, 0); + + gdk_threads_leave (); + + return jpixels; +} diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c index 1cb4334..94e98bf 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c @@ -315,10 +315,12 @@ focus_in_cb (GtkWidget *widget __attribute((unused)), GdkEventFocus *event __attribute((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postFocusEventID, AWT_FOCUS_GAINED, JNI_FALSE); + gdk_threads_enter (); return FALSE; } @@ -327,21 +329,27 @@ focus_out_cb (GtkWidget *widget __attribute((unused)), GdkEventFocus *event __attribute((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postFocusEventID, AWT_FOCUS_LOST, JNI_FALSE); + gdk_threads_enter (); return FALSE; } static void block_expose_events_cb (GtkWidget *widget, jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, beginNativeRepaintID); + gdk_threads_enter (); gdk_window_process_updates (widget->window, TRUE); - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, endNativeRepaintID); + gdk_threads_enter (); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c index 3b58c05..6c854ef 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c @@ -208,7 +208,7 @@ Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkButtonSetLabel static void item_toggled (GtkToggleButton *item, jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postItemEventID, peer, item->active ? diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c index 94c9c3d..b4e64e6 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c @@ -39,22 +39,24 @@ exception statement from your version. */ #include "gtkpeer.h" #include "gnu_java_awt_peer_gtk_GtkChoicePeer.h" -static void selection_changed (GtkComboBox *combobox, gpointer data); +static void selection_changed (GtkComboBox *combobox, jobject peer); JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkChoicePeer_create (JNIEnv *env, jobject obj) { GtkWidget *combobox; + jobject *gref; NSA_SET_GLOBAL_REF (env, obj); + gref = NSA_GET_GLOBAL_REF (env, obj); gdk_threads_enter (); combobox = gtk_combo_box_new_text (); g_signal_connect (combobox, "changed", - G_CALLBACK (selection_changed), obj); + G_CALLBACK (selection_changed), *gref); gdk_threads_leave (); @@ -175,7 +177,7 @@ Java_gnu_java_awt_peer_gtk_GtkChoicePeer_nativeGetSelected return index; } -void selection_changed (GtkComboBox *combobox, jobject peer) +static void selection_changed (GtkComboBox *combobox, jobject peer) { jstring label; GtkTreeModel *model; @@ -195,8 +197,8 @@ void selection_changed (GtkComboBox *combobox, jobject peer) gdk_threads_leave (); - label = (*gdk_env)->NewStringUTF (gdk_env, selected); - (*gdk_env)->CallVoidMethod (gdk_env, peer, + label = (*gdk_env())->NewStringUTF (gdk_env(), selected); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, choicePostItemEventID, label, (jint) AWT_ITEM_SELECTED); diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c index 986244e..e051857 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkClipboard.c @@ -110,15 +110,15 @@ selection_received (GtkWidget *widget __attribute__((unused)), if (selection_data->length < 0 || selection_data->type != GDK_SELECTION_TYPE_STRING) { - (*gdk_env)->CallVoidMethod (gdk_env, cb_obj, stringSelectionReceivedID, - NULL); + (*gdk_env())->CallVoidMethod (gdk_env(), cb_obj, stringSelectionReceivedID, + NULL); } else { char *str = (char *) selection_data->data; - (*gdk_env)->CallVoidMethod (gdk_env, cb_obj, stringSelectionReceivedID, - (*gdk_env)->NewStringUTF (gdk_env, str)); + (*gdk_env())->CallVoidMethod (gdk_env(), cb_obj, stringSelectionReceivedID, + (*gdk_env())->NewStringUTF (gdk_env(), str)); } return; @@ -135,7 +135,7 @@ selection_get (GtkWidget *widget __attribute__((unused)), const char *utf; jsize utflen; - jstr = (*gdk_env)->CallObjectMethod (gdk_env, cb_obj, + jstr = (*gdk_env())->CallObjectMethod (gdk_env(), cb_obj, stringSelectionHandlerID); if (!jstr) @@ -145,13 +145,13 @@ selection_get (GtkWidget *widget __attribute__((unused)), return; } - utflen = (*gdk_env)->GetStringUTFLength (gdk_env, jstr); - utf = (*gdk_env)->GetStringUTFChars (gdk_env, jstr, NULL); + utflen = (*gdk_env())->GetStringUTFLength (gdk_env(), jstr); + utf = (*gdk_env())->GetStringUTFChars (gdk_env(), jstr, NULL); gtk_selection_data_set (selection_data, GDK_TARGET_STRING, 8, (const unsigned char*)utf, utflen); - (*gdk_env)->ReleaseStringUTFChars (gdk_env, jstr, utf); + (*gdk_env())->ReleaseStringUTFChars (gdk_env(), jstr, utf); } JNIEXPORT void JNICALL @@ -177,7 +177,7 @@ gint selection_clear (GtkWidget *widget __attribute__((unused)), GdkEventSelection *event __attribute__((unused))) { - (*gdk_env)->CallVoidMethod (gdk_env, cb_obj, selectionClearID); + (*gdk_env())->CallVoidMethod (gdk_env(), cb_obj, selectionClearID); return TRUE; } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c index 3aebe77..4cd3f16 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c @@ -60,7 +60,7 @@ static gboolean focus_out_cb (GtkWidget *widget, #ifdef __GNUC__ __inline #endif -static guint +guint awt_keycode_to_keysym (jint keyCode, jint keyLocation) { /* GDK_A through GDK_Z */ @@ -1054,10 +1054,12 @@ focus_in_cb (GtkWidget *widget __attribute((unused)), GdkEventFocus *event __attribute((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postFocusEventID, AWT_FOCUS_GAINED, JNI_FALSE); + gdk_threads_enter (); return FALSE; } @@ -1066,9 +1068,11 @@ focus_out_cb (GtkWidget *widget __attribute((unused)), GdkEventFocus *event __attribute((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postFocusEventID, AWT_FOCUS_LOST, JNI_FALSE); + gdk_threads_enter (); return FALSE; } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c index 65f64e04..7ad20b8 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c @@ -883,7 +883,8 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) switch (event->type) { case GDK_BUTTON_PRESS: - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postMouseEventID, AWT_MOUSE_PRESSED, (jlong)event->button.time, @@ -894,13 +895,15 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) click_count, (event->button.button == 3) ? JNI_TRUE : JNI_FALSE); + gdk_threads_enter (); hasBeenDragged = FALSE; break; case GDK_BUTTON_RELEASE: { int width, height; - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postMouseEventID, AWT_MOUSE_RELEASED, (jlong)event->button.time, @@ -910,6 +913,7 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) (jint)event->button.y, click_count, JNI_FALSE); + gdk_threads_enter (); /* Generate an AWT click event only if the release occured in the window it was pressed in, and the mouse has not been dragged since @@ -921,7 +925,8 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) && event->button.x <= width && event->button.y <= height) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postMouseEventID, AWT_MOUSE_CLICKED, (jlong)event->button.time, @@ -931,6 +936,7 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) (jint)event->button.y, click_count, JNI_FALSE); + gdk_threads_enter (); } } break; @@ -941,7 +947,8 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) | GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postMouseEventID, AWT_MOUSE_DRAGGED, (jlong)event->motion.time, @@ -950,44 +957,58 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) (jint)event->motion.y, 0, JNI_FALSE); + gdk_threads_enter (); hasBeenDragged = TRUE; } else - (*gdk_env)->CallVoidMethod (gdk_env, peer, postMouseEventID, - AWT_MOUSE_MOVED, - (jlong)event->motion.time, - state_to_awt_mods (event->motion.state), - (jint)event->motion.x, - (jint)event->motion.y, - 0, - JNI_FALSE); + { + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postMouseEventID, + AWT_MOUSE_MOVED, + (jlong)event->motion.time, + state_to_awt_mods (event->motion.state), + (jint)event->motion.x, + (jint)event->motion.y, + 0, + JNI_FALSE); + gdk_threads_enter (); + } + break; case GDK_ENTER_NOTIFY: /* We are not interested in enter events that are due to grab/ungrab and not to actually crossing boundaries */ if (event->crossing.mode == GDK_CROSSING_NORMAL) - (*gdk_env)->CallVoidMethod (gdk_env, peer, postMouseEventID, - AWT_MOUSE_ENTERED, - (jlong)event->crossing.time, - state_to_awt_mods_with_button_states (event->crossing.state), - (jint)event->crossing.x, - (jint)event->crossing.y, - 0, - JNI_FALSE); + { + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postMouseEventID, + AWT_MOUSE_ENTERED, + (jlong)event->crossing.time, + state_to_awt_mods_with_button_states (event->crossing.state), + (jint)event->crossing.x, + (jint)event->crossing.y, + 0, + JNI_FALSE); + gdk_threads_enter (); + } break; case GDK_LEAVE_NOTIFY: /* We are not interested in leave events that are due to grab/ungrab and not to actually crossing boundaries */ if (event->crossing.mode == GDK_CROSSING_NORMAL) - (*gdk_env)->CallVoidMethod (gdk_env, peer, - postMouseEventID, - AWT_MOUSE_EXITED, - (jlong)event->crossing.time, - state_to_awt_mods_with_button_states (event->crossing.state), - (jint)event->crossing.x, - (jint)event->crossing.y, - 0, - JNI_FALSE); + { + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, + postMouseEventID, + AWT_MOUSE_EXITED, + (jlong)event->crossing.time, + state_to_awt_mods_with_button_states (event->crossing.state), + (jint)event->crossing.x, + (jint)event->crossing.y, + 0, + JNI_FALSE); + gdk_threads_enter (); + } break; case GDK_CONFIGURE: { @@ -1001,7 +1022,7 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) returns. */ gdk_threads_leave (); - (*gdk_env)->CallVoidMethod (gdk_env, peer, + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postConfigureEventID, (jint) event->configure.x, (jint) event->configure.y, @@ -1012,20 +1033,24 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) } break; case GDK_EXPOSE: - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postExposeEventID, (jint)event->expose.area.x, (jint)event->expose.area.y, (jint)event->expose.area.width, (jint)event->expose.area.height); + gdk_threads_enter (); break; case GDK_FOCUS_CHANGE: - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postFocusEventID, (jint) (event->focus_change.in) ? AWT_FOCUS_GAINED : AWT_FOCUS_LOST, JNI_FALSE); + gdk_threads_enter (); break; case GDK_KEY_PRESS: if (GTK_IS_WINDOW (widget)) @@ -1033,7 +1058,8 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) /* GdkEventKey *keyevent = (GdkEventKey *) event; */ /* g_printerr ("key press event: sent: %d time: %d state: %d keyval: %d length: %d string: %s hardware_keycode: %d group: %d\n", keyevent->send_event, keyevent->time, keyevent->state, keyevent->keyval, keyevent->length, keyevent->string, keyevent->hardware_keycode, keyevent->group); */ - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postKeyEventID, (jint) AWT_KEY_PRESSED, (jlong) event->key.time, @@ -1041,6 +1067,7 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) keysym_to_awt_keycode (event), keyevent_to_awt_keychar (event), keysym_to_awt_keylocation (event)); + gdk_threads_enter (); /* FIXME: generation of key typed events needs to be moved to GtkComponentPeer.postKeyEvent. If the key in a key press event is not an "action" key @@ -1054,7 +1081,8 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) case GDK_KEY_RELEASE: if (GTK_IS_WINDOW (widget)) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postKeyEventID, (jint) AWT_KEY_RELEASED, (jlong) event->key.time, @@ -1062,6 +1090,7 @@ pre_event_handler (GtkWidget *widget, GdkEvent *event, jobject peer) keysym_to_awt_keycode (event), keyevent_to_awt_keychar (event), keysym_to_awt_keylocation (event)); + gdk_threads_enter (); return TRUE; } else @@ -1135,13 +1164,13 @@ void connect_awt_hook_cb (GtkWidget *widget __attribute__((unused)), { void *ptr; - ptr = NSA_GET_PTR (gdk_env, peer); + ptr = NSA_GET_PTR (gdk_env(), peer); - connect_awt_hook (gdk_env, peer, 1, GTK_WIDGET (ptr)->window); + connect_awt_hook (gdk_env(), peer, 1, GTK_WIDGET (ptr)->window); gdk_threads_leave (); - (*gdk_env)->CallVoidMethod (gdk_env, peer, setCursorID); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, setCursorID); gdk_threads_enter (); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c index 3a2e41f..7919161 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c @@ -41,8 +41,8 @@ exception statement from your version. */ #include "gnu_java_awt_peer_gtk_GtkFileDialogPeer.h" static void handle_response (GtkDialog *dialog, - gint responseId, - jobject peer_obj); + gint responseId, + jobject peer_obj); /* * Make a new file selection dialog @@ -62,15 +62,17 @@ Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_create gdk_threads_enter (); - widget = gtk_file_chooser_dialog_new("", - GTK_WINDOW(parentp), - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_OK, GTK_RESPONSE_OK, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - NULL); - - /* GtkFileChooser doesn't show hidden files by default. */ - g_object_set(GTK_FILE_CHOOSER(widget), "show_hidden", TRUE); + /* FIXME: we should be using the default gnome-vfs backend but it is + not currently thread-safe. See: + http://bugzilla.gnome.org/show_bug.cgi?id=166852 */ + widget = gtk_file_chooser_dialog_new_with_backend + ("Open File", + GTK_WINDOW(parentp), + GTK_FILE_CHOOSER_ACTION_OPEN, + "gtk+", + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); /* GtkFileSelect is not modal by default */ gtk_window_set_modal (GTK_WINDOW (widget), TRUE); @@ -97,7 +99,7 @@ Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_connectSignals g_signal_connect (G_OBJECT (GTK_DIALOG (ptr)), "response", GTK_SIGNAL_FUNC (handle_response), *gref); - + gdk_threads_leave (); /* Connect the superclass signals. */ @@ -112,7 +114,7 @@ Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeGetDirectory const char *str; ptr = NSA_GET_PTR (env, obj); - + gdk_threads_enter (); str = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER(ptr)); @@ -135,14 +137,14 @@ static gboolean filenameFilterCallback (const GtkFileFilterInfo *filter_info, jstring *filename; gboolean accepted; - cx = (*gdk_env)->GetObjectClass (gdk_env, (jobject) obj); - id = (*gdk_env)->GetMethodID (gdk_env, cx, "filenameFilterCallback", + cx = (*gdk_env())->GetObjectClass (gdk_env(), (jobject) obj); + id = (*gdk_env())->GetMethodID (gdk_env(), cx, "filenameFilterCallback", "(Ljava/lang/String;)Z"); - filename = (*gdk_env)->NewStringUTF(gdk_env, filter_info->filename); - + filename = (*gdk_env())->NewStringUTF(gdk_env(), filter_info->filename); + gdk_threads_leave(); - accepted = (*gdk_env)->CallBooleanMethod(gdk_env, obj, id, filename); + accepted = (*gdk_env())->CallBooleanMethod(gdk_env(), obj, id, filename); gdk_threads_enter(); return accepted; @@ -166,8 +168,8 @@ Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetFilenameFilter gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(ptr), filter); gdk_threads_leave (); - } - +} + JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetDirectory (JNIEnv *env, jobject obj, jstring directory) @@ -196,7 +198,7 @@ Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetFile ptr = NSA_GET_PTR (env, obj); str = (*env)->GetStringUTFChars (env, filename, 0); - + gdk_threads_enter (); gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (ptr), str); gdk_threads_leave (); @@ -207,7 +209,7 @@ Java_gnu_java_awt_peer_gtk_GtkFileDialogPeer_nativeSetFile static void handle_response (GtkDialog *dialog __attribute__((unused)), gint responseId, - jobject peer_obj) + jobject peer_obj) { static int isDisposeIDSet = 0; static int isIDSet = 0; @@ -221,51 +223,51 @@ handle_response (GtkDialog *dialog __attribute__((unused)), /* We only need this for the case when the user closed the window, or clicked ok or cancel. */ if (responseId != GTK_RESPONSE_DELETE_EVENT - && responseId != GTK_RESPONSE_OK + && responseId != GTK_RESPONSE_ACCEPT && responseId != GTK_RESPONSE_CANCEL) return; - - ptr = NSA_GET_PTR (gdk_env, peer_obj); - + + ptr = NSA_GET_PTR (gdk_env(), peer_obj); + if (responseId == GTK_RESPONSE_DELETE_EVENT) { if (!isDisposeIDSet) - { - jclass cx = (*gdk_env)->GetObjectClass (gdk_env, peer_obj); - disposeID = (*gdk_env)->GetMethodID (gdk_env, cx, "gtkDisposeFileDialog", "()V"); + { + jclass cx = (*gdk_env())->GetObjectClass (gdk_env(), peer_obj); + disposeID = (*gdk_env())->GetMethodID (gdk_env(), cx, "gtkDisposeFileDialog", "()V"); isDisposeIDSet = 1; - } - - gdk_threads_leave (); + } + gdk_threads_leave (); + /* We can dispose of the dialog now (and unblock show) */ - (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, disposeID); + (*gdk_env())->CallVoidMethod (gdk_env(), peer_obj, disposeID); - gdk_threads_enter (); + gdk_threads_enter (); return; -} + } - if (responseId == GTK_RESPONSE_OK) { + if (responseId == GTK_RESPONSE_ACCEPT) { fileName = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (GTK_WIDGET (ptr))); - str_fileName = (*gdk_env)->NewStringUTF (gdk_env, fileName); + str_fileName = (*gdk_env())->NewStringUTF (gdk_env(), fileName); } - + if (!isIDSet) { - jclass cx = (*gdk_env)->GetObjectClass (gdk_env, peer_obj); - hideID = (*gdk_env)->GetMethodID (gdk_env, cx, "gtkHideFileDialog", "()V"); - gtkSetFilenameID = (*gdk_env)->GetMethodID (gdk_env, cx, + jclass cx = (*gdk_env())->GetObjectClass (gdk_env(), peer_obj); + hideID = (*gdk_env())->GetMethodID (gdk_env(), cx, "gtkHideFileDialog", "()V"); + gtkSetFilenameID = (*gdk_env())->GetMethodID (gdk_env(), cx, "gtkSetFilename", "(Ljava/lang/String;)V"); isIDSet = 1; } gdk_threads_leave (); - + /* Set the Java object field 'file' with this value. */ - (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, gtkSetFilenameID, str_fileName); + (*gdk_env())->CallVoidMethod (gdk_env(), peer_obj, gtkSetFilenameID, str_fileName); /* We can hide the dialog now (and unblock show) */ - (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, hideID); + (*gdk_env())->CallVoidMethod (gdk_env(), peer_obj, hideID); gdk_threads_enter (); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c index 5c48832..52da40c 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFramePeer.c @@ -177,3 +177,47 @@ Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImageFromDecoder gdk_threads_leave (); } + +static void +free_pixbuf_data (guchar *pixels, gpointer data __attribute__((unused))) +{ + free(pixels); +} + +JNIEXPORT void JNICALL +Java_gnu_java_awt_peer_gtk_GtkFramePeer_nativeSetIconImageFromData + (JNIEnv *env, jobject obj, jintArray pixelArray, jint width, jint height) +{ + void *ptr; + GdkPixbuf *pixbuf; + jint *pixels; + int pixels_length, i; + guchar *data; + + ptr = NSA_GET_PTR (env, obj); + + pixels = (*env)->GetIntArrayElements (env, pixelArray, 0); + pixels_length = (*env)->GetArrayLength (env, pixelArray); + + data = malloc (sizeof (guchar) * pixels_length); + for (i = 0; i < pixels_length; i++) + data[i] = (guchar) pixels[i]; + + gdk_threads_enter (); + + pixbuf = gdk_pixbuf_new_from_data (data, + GDK_COLORSPACE_RGB, + TRUE, + 8, + width, + height, + width*4, + free_pixbuf_data, + NULL); + + gtk_window_set_icon (GTK_WINDOW (ptr), pixbuf); + + gdk_threads_leave (); + + (*env)->ReleaseIntArrayElements(env, pixelArray, pixels, 0); +} diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c index 8eebce9..49ccffc 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkGenericPeer.c @@ -45,9 +45,7 @@ Java_gnu_java_awt_peer_gtk_GtkGenericPeer_dispose { void *ptr; - /* Remove entries from state tables */ - NSA_DEL_GLOBAL_REF (env, obj); - ptr = NSA_DEL_PTR (env, obj); + ptr = NSA_GET_PTR (env, obj); gdk_threads_enter (); @@ -56,6 +54,17 @@ Java_gnu_java_awt_peer_gtk_GtkGenericPeer_dispose gtk_widget_destroy (GTK_WIDGET (ptr)); gdk_threads_leave (); + + /* Remove entries from state tables */ + NSA_DEL_GLOBAL_REF (env, obj); + NSA_DEL_PTR (env, obj); + + /* + * Wake up the main thread, to make sure it re-checks the window + * destruction condition. + */ + + g_main_context_wakeup (NULL); } JNIEXPORT void JNICALL diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c index 575f3c9..468be06 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkListPeer.c @@ -1,5 +1,5 @@ -/* gtklistpeer.c -- Native implementation of GtkListPeer - Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. +/* GtkListPeer.c -- implements GtkListPeer's native methods + Copyright (C) 1998, 1999, 2003, 2004 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -498,12 +498,12 @@ item_highlighted (GtkTreeSelection *selection __attribute__((unused)), row = indices ? indices[0] : -1; if (!path_currently_selected) - (*gdk_env)->CallVoidMethod (gdk_env, peer, + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postListItemEventID, row, (jint) AWT_ITEM_SELECTED); else - (*gdk_env)->CallVoidMethod (gdk_env, peer, + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postListItemEventID, row, (jint) AWT_ITEM_DESELECTED); diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c deleted file mode 100644 index 8a2a810..0000000 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c +++ /dev/null @@ -1,307 +0,0 @@ -/* gtkmainthread.c -- Native implementation of GtkMainThread - Copyright (C) 1998, 1999, 2002 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. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -#include "gtkpeer.h" -#include "gnu_java_awt_peer_gtk_GtkMainThread.h" -#include "gthread-jni.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 beginNativeRepaintID; -jmethodID endNativeRepaintID; - -jmethodID initComponentGraphicsID; -jmethodID initComponentGraphics2DID; -jmethodID setCursorID; - -JNIEnv *gdk_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); - -/* - * 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_GtkMainThread_gtkInit (JNIEnv *env, jclass clazz, - jint portableNativeSync) -{ - int argc = 1; - char **argv; - char *homedir, *rcpath = NULL; - jclass gtkcomponentpeer, gtkchoicepeer, gtkwindowpeer, gtkscrollbarpeer, gtklistpeer, - gtkmenuitempeer, gtktextcomponentpeer, window, gdkgraphics, gdkgraphics2d; - - NSA_INIT (env, clazz); - gdk_env = env; - - /* 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); -#if 1 - strcpy(argv[0], ""); -#else /* The following is a more efficient alternative, but less intuitively - * expresses what we are trying to do. This code is only run once, so - * I'm going for intuitive. */ - argv[0][0] = '\0'; -#endif - argv[1] = NULL; - - init_glib_threads(env, portableNativeSync); - - /* From GDK 2.0 onwards we have to explicitly call gdk_threads_init */ - 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 ()); - - /* Make sure queued calls don't get sent to GTK/GDK while - we're shutting down. */ - 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); - - /* setup cached IDs for posting GTK events to Java */ - - 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"); - 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 (); -} - - -/** 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) -{ - 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, &the_vm ); - if (portableNativeSync) - g_thread_init ( &portable_native_sync_jni_functions ); - else - g_thread_init ( NULL ); - - /* Debugging progress message; uncomment if needed: */ - /* printf("called gthread init\n"); */ -} - - - -/* - * Run gtk_main and block. - */ -JNIEXPORT void JNICALL -Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkMain - (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused))) -{ - gdk_threads_enter (); - gtk_main (); - gdk_threads_leave (); -} - -/* This is a big hack, needed until this pango bug is resolved: - http://bugzilla.gnome.org/show_bug.cgi?id=119081. - See: http://mail.gnome.org/archives/gtk-i18n-list/2003-August/msg00001.html - for details. */ -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 == -1 gtk-xft-dpi returns the default value. So we - have to do approximate calculation here. */ - 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 - /* Approximate. */ - 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); -} diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c index 4d68fce..1fe18f9 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c @@ -165,6 +165,6 @@ Java_gnu_java_awt_peer_gtk_GtkMenuItemPeer_setLabel static void item_activate (GtkMenuItem *item __attribute__((unused)), jobject peer_obj) { - (*gdk_env)->CallVoidMethod (gdk_env, peer_obj, + (*gdk_env())->CallVoidMethod (gdk_env(), peer_obj, postMenuActionEventID); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollBarPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollBarPeer.c index 4f83446..790c901 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollBarPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkScrollBarPeer.c @@ -160,6 +160,6 @@ post_change_event (GtkRange *range, jobject peer) { GtkAdjustment *adj; adj = gtk_range_get_adjustment (range); - (*gdk_env)->CallVoidMethod (gdk_env, peer, postAdjustmentEventID, + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postAdjustmentEventID, AWT_ADJUSTMENT_TRACK, (jint) adj->value); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c index 771f2b8..6eb06e0 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextComponentPeer.c @@ -492,5 +492,7 @@ static void textcomponent_changed_cb (GtkEditable *editable __attribute__((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, postTextEventID); + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postTextEventID); + gdk_threads_enter (); } diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c index 6234b29..81857c4 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkToolkit.c @@ -38,9 +38,364 @@ exception statement from your version. */ #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 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); + +/* + * 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) +{ + 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); + + /* 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); +#if 1 + strcpy(argv[0], ""); +#else /* The following is a more efficient alternative, but less intuitively + * expresses what we are trying to do. This code is only run once, so + * I'm going for intuitive. */ + argv[0][0] = '\0'; +#endif + argv[1] = NULL; + + init_glib_threads(env, portableNativeSync); + + /* From GDK 2.0 onwards we have to explicitly call gdk_threads_init */ + 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 ()); + + /* Make sure queued calls don't get sent to GTK/GDK while + we're shutting down. */ + 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); + + /* setup cached IDs for posting GTK events to Java */ + + 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"); + 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 (); +} + + +/** 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) +{ + 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, &the_vm ); + if (portableNativeSync) + g_thread_init ( &portable_native_sync_jni_functions ); + else + g_thread_init ( NULL ); + + /* Debugging progress message; uncomment if needed: */ + /* printf("called gthread init\n"); */ +} + + +/* This is a big hack, needed until this pango bug is resolved: + http://bugzilla.gnome.org/show_bug.cgi?id=119081. + See: http://mail.gnome.org/archives/gtk-i18n-list/2003-August/msg00001.html + for details. */ +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 == -1 gtk-xft-dpi returns the default value. So we + have to do approximate calculation here. */ + 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 + /* Approximate. */ + 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) +{ + /* We're holding an EventQueue lock, and we're about to acquire the GDK + * lock before dropping the EventQueue lock. This can deadlock if someone + * holds the GDK lock and wants to acquire the EventQueue lock; however + * all callbacks from GTK happen with the GDK lock released, so this + * would only happen in an odd case such as some JNI helper code + * acquiring the GDK lock and calling back into + * EventQueue.getNextEvent(). + */ + + struct timeval init; + gettimeofday(&init, NULL); + + gdk_threads_enter (); + (*env)->MonitorExit (env, lockedQueue); + + if (block) + { + + /* If we're blocking-when-empty, we want a do .. while loop. */ + do + gtk_main_iteration (); + while (within_human_latency_tolerance (&init) + && gtk_events_pending ()); + } + else + { + /* If we're not blocking-when-empty, we want a while loop. */ + 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))) diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c index a8e745e..2ca7f83 100644 --- a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c +++ b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c @@ -65,8 +65,8 @@ static void window_active_state_change_cb (GtkWidget *widget, GParamSpec *pspec, jobject peer); static void window_focus_state_change_cb (GtkWidget *widget, - GParamSpec *pspec, - jobject peer); + GParamSpec *pspec, + jobject peer); static gboolean window_focus_in_cb (GtkWidget * widget, GdkEventFocus *event, jobject peer); @@ -320,7 +320,7 @@ Java_gnu_java_awt_peer_gtk_GtkWindowPeer_setBoundsCallback { /* Circumvent package-private access to call Window's setBoundsCallback method. */ - (*gdk_env)->CallVoidMethod (gdk_env, window, setBoundsCallbackID, + (*gdk_env())->CallVoidMethod (gdk_env(), window, setBoundsCallbackID, x, y, width, height); } @@ -483,9 +483,9 @@ property_notify_predicate (Display *xdisplay __attribute__((unused)), if (event->xany.type == PropertyNotify && event->xany.window == *window && event->xproperty.atom == extents_atom) - return True; + return True; else - return False; + return False; } static void @@ -493,10 +493,12 @@ window_delete_cb (GtkWidget *widget __attribute__((unused)), GdkEvent *event __attribute__((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_CLOSING, (jobject) NULL, (jint) 0); + gdk_threads_enter (); } static void @@ -504,20 +506,24 @@ window_destroy_cb (GtkWidget *widget __attribute__((unused)), GdkEvent *event __attribute__((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_CLOSED, (jobject) NULL, (jint) 0); + gdk_threads_enter (); } static void window_show_cb (GtkWidget *widget __attribute__((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_OPENED, (jobject) NULL, (jint) 0); + gdk_threads_enter (); } static void @@ -528,47 +534,53 @@ window_active_state_change_cb (GtkWidget *widget __attribute__((unused)), /* FIXME: not sure if this is needed or not. */ /* Remove the unused attributes if you fix the below. */ #if 0 - if (GTK_WINDOW (widget)->is_active) - (*gdk_env)->CallVoidMethod (gdk_env, peer, - postWindowEventID, - (jint) AWT_WINDOW_GAINED_FOCUS, - (jobject) NULL, (jint) 0); - else - (*gdk_env)->CallVoidMethod (gdk_env, peer, - postWindowEventID, - (jint) AWT_WINDOW_DEACTIVATED, - (jobject) NULL, (jint) 0); + gdk_threads_leave (); + if (GTK_WINDOW (widget)->is_active) + (*gdk_env())->CallVoidMethod (gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_GAINED_FOCUS, + (jobject) NULL, (jint) 0); + else + (*gdk_env())->CallVoidMethod (gdk_env(), peer, + postWindowEventID, + (jint) AWT_WINDOW_DEACTIVATED, + (jobject) NULL, (jint) 0); + gdk_threads_enter (); #endif - } +} static void window_focus_state_change_cb (GtkWidget *widget, GParamSpec *pspec __attribute__((unused)), jobject peer) { + gdk_threads_leave (); if (GTK_WINDOW (widget)->has_toplevel_focus) - (*gdk_env)->CallVoidMethod (gdk_env, peer, + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_ACTIVATED, (jobject) NULL, (jint) 0); else - (*gdk_env)->CallVoidMethod (gdk_env, peer, + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_DEACTIVATED, - (jobject) NULL, (jint) 0); - } + (jobject) NULL, (jint) 0); + gdk_threads_enter (); +} static gboolean window_focus_in_cb (GtkWidget * widget __attribute__((unused)), GdkEventFocus *event __attribute__((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_GAINED_FOCUS, (jobject) NULL, (jint) 0); /* FIXME: somewhere after this is handled, the child window is getting an expose event. */ + gdk_threads_enter (); return FALSE; } @@ -577,12 +589,14 @@ window_focus_out_cb (GtkWidget * widget __attribute__((unused)), GdkEventFocus *event __attribute__((unused)), jobject peer) { - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_LOST_FOCUS, (jobject) NULL, (jint) 0); /* FIXME: somewhere after this is handled, the child window is getting an expose event. */ + gdk_threads_enter (); return FALSE; } @@ -600,18 +614,22 @@ window_window_state_cb (GtkWidget *widget, if (event->window_state.new_window_state & GDK_WINDOW_STATE_ICONIFIED) { /* We've been iconified. */ - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_ICONIFIED, (jobject) NULL, (jint) 0); + gdk_threads_enter (); } else { /* We've been deiconified. */ - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_DEICONIFIED, (jobject) NULL, (jint) 0); + gdk_threads_enter (); } } @@ -624,10 +642,12 @@ window_window_state_cb (GtkWidget *widget, new_state |= window_get_new_state (widget); - (*gdk_env)->CallVoidMethod (gdk_env, peer, + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, postWindowEventID, (jint) AWT_WINDOW_STATE_CHANGED, (jobject) NULL, new_state); + gdk_threads_enter (); return TRUE; } @@ -685,9 +705,9 @@ window_property_changed_cb (GtkWidget *widget __attribute__((unused)), if (!id_set) { - jclass gtkwindowpeer = (*gdk_env)->FindClass (gdk_env, + jclass gtkwindowpeer = (*gdk_env())->FindClass (gdk_env(), "gnu/java/awt/peer/gtk/GtkWindowPeer"); - postInsetsChangedEventID = (*gdk_env)->GetMethodID (gdk_env, + postInsetsChangedEventID = (*gdk_env())->GetMethodID (gdk_env(), gtkwindowpeer, "postInsetsChangedEvent", "(IIII)V"); @@ -705,12 +725,17 @@ window_property_changed_cb (GtkWidget *widget __attribute__((unused)), NULL, NULL, gu_ex.gu_extents)) - (*gdk_env)->CallVoidMethod (gdk_env, peer, - postInsetsChangedEventID, - (jint) extents[2], /* top */ - (jint) extents[0], /* left */ - (jint) extents[3], /* bottom */ - (jint) extents[1]); /* right */ + { + gdk_threads_leave (); + (*gdk_env())->CallVoidMethod (gdk_env(), peer, + postInsetsChangedEventID, + (jint) extents[2], /* top */ + (jint) extents[0], /* left */ + (jint) extents[3], /* bottom */ + (jint) extents[1]); /* right */ + gdk_threads_enter (); + } + return FALSE; } diff --git a/libjava/jni/gtk-peer/gtkcairopeer.h b/libjava/jni/gtk-peer/gtkcairopeer.h index b4021f5..85834ca 100644 --- a/libjava/jni/gtk-peer/gtkcairopeer.h +++ b/libjava/jni/gtk-peer/gtkcairopeer.h @@ -74,6 +74,19 @@ struct graphics2d cairo_surface_t *pattern_surface; cairo_pattern_t *pattern; gboolean debug; + enum + { + MODE_DRAWABLE_WITH_RENDER, + MODE_DRAWABLE_NO_RENDER, + MODE_JAVA_ARRAY + } + mode; + + /* Support for MODE_JAVA_ARRAY */ + jintArray jarray; + jint width, height; + jint *javabuf; + jboolean isCopy; }; #endif /* __GTKCAIROPEER_H */ diff --git a/libjava/jni/gtk-peer/gtkpeer.h b/libjava/jni/gtk-peer/gtkpeer.h index e982551..9b04bb1 100644 --- a/libjava/jni/gtk-peer/gtkpeer.h +++ b/libjava/jni/gtk-peer/gtkpeer.h @@ -147,6 +147,10 @@ struct graphics #define AWT_BUTTON2_DOWN_MASK (1 << 11) #define AWT_BUTTON3_DOWN_MASK (1 << 12) +#define AWT_BUTTON1_MASK (1 << 4) +#define AWT_BUTTON2_MASK (1 << 3) +#define AWT_BUTTON3_MASK (1 << 2) + #define MULTI_CLICK_TIME 250 /* as opposed to a MULTI_PASS_TIME :) */ @@ -460,7 +464,8 @@ extern jmethodID setCursorID; extern jmethodID syncAttrsID; extern jclass gdkColor; extern jmethodID gdkColorID; -extern JNIEnv *gdk_env; + +JNIEnv *gdk_env(void); extern double dpi_conversion_factor; @@ -480,6 +485,8 @@ void set_parent (GtkWidget *widget, GtkContainer *parent); jint keyevent_state_to_awt_mods (GdkEvent *event); +guint awt_keycode_to_keysym (jint keyCode, jint keyLocation); + struct item_event_hook_info { jobject peer_obj; |