Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/awt/gtk2_interface.c
32287 views
/*1* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24#include <dlfcn.h>25#include <setjmp.h>26#include <X11/Xlib.h>27#include <limits.h>28#include <stdio.h>29#include <string.h>30#include "gtk2_interface.h"31#include "java_awt_Transparency.h"32#include "jvm_md.h"33#include "sizecalc.h"34#include <jni_util.h>35#include "awt.h"3637#define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)())3839#define G_TYPE_FUNDAMENTAL_SHIFT (2)40#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))4142#define CONV_BUFFER_SIZE 1284344#define NO_SYMBOL_EXCEPTION 14546static void *gtk2_libhandle = NULL;47static void *gthread_libhandle = NULL;4849static jmp_buf j;5051/* Widgets */52static GtkWidget *gtk2_widget = NULL;53static GtkWidget *gtk2_window = NULL;54static GtkFixed *gtk2_fixed = NULL;5556/* Paint system */57static GdkPixmap *gtk2_white_pixmap = NULL;58static GdkPixmap *gtk2_black_pixmap = NULL;59static GdkPixbuf *gtk2_white_pixbuf = NULL;60static GdkPixbuf *gtk2_black_pixbuf = NULL;61static int gtk2_pixbuf_width = 0;62static int gtk2_pixbuf_height = 0;6364/* Static buffer for conversion from java.lang.String to UTF-8 */65static char convertionBuffer[CONV_BUFFER_SIZE];6667static gboolean new_combo = TRUE;68const char ENV_PREFIX[] = "GTK_MODULES=";6970static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE];7172/*************************73* Glib function pointers74*************************/7576static gboolean (*fp_g_main_context_iteration)(GMainContext *context,77gboolean may_block);7879static GValue* (*fp_g_value_init)(GValue *value, GType g_type);80static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type);81static gboolean (*fp_g_value_get_boolean)(const GValue *value);82static gchar (*fp_g_value_get_char)(const GValue *value);83static guchar (*fp_g_value_get_uchar)(const GValue *value);84static gint (*fp_g_value_get_int)(const GValue *value);85static guint (*fp_g_value_get_uint)(const GValue *value);86static glong (*fp_g_value_get_long)(const GValue *value);87static gulong (*fp_g_value_get_ulong)(const GValue *value);88static gint64 (*fp_g_value_get_int64)(const GValue *value);89static guint64 (*fp_g_value_get_uint64)(const GValue *value);90static gfloat (*fp_g_value_get_float)(const GValue *value);91static gdouble (*fp_g_value_get_double)(const GValue *value);92static const gchar* (*fp_g_value_get_string)(const GValue *value);93static gint (*fp_g_value_get_enum)(const GValue *value);94static guint (*fp_g_value_get_flags)(const GValue *value);95static GParamSpec* (*fp_g_value_get_param)(const GValue *value);96static gpointer* (*fp_g_value_get_boxed)(const GValue *value);97static gpointer* (*fp_g_value_get_pointer)(const GValue *value);98static GObject* (*fp_g_value_get_object)(const GValue *value);99static GParamSpec* (*fp_g_param_spec_int)(const gchar *name,100const gchar *nick, const gchar *blurb,101gint minimum, gint maximum, gint default_value,102GParamFlags flags);103static void (*fp_g_object_get)(gpointer object,104const gchar* fpn, ...);105static void (*fp_g_object_set)(gpointer object,106const gchar *first_property_name,107...);108/************************109* GDK function pointers110************************/111static GdkPixmap *(*fp_gdk_pixmap_new)(GdkDrawable *drawable,112gint width, gint height, gint depth);113static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*);114static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32);115static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean,116gint, gint, gint, gint);117static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace,118gboolean has_alpha, int bits_per_sample, int width, int height);119static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest,120GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y,121int dest_x, int dest_y, int width, int height);122static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable,123gint* width, gint* height);124125/************************126* Gtk function pointers127************************/128static gboolean (*fp_gtk_init_check)(int* argc, char** argv);129130/* Painting */131static void (*fp_gtk_paint_hline)(GtkStyle* style, GdkWindow* window,132GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,133const gchar* detail, gint x1, gint x2, gint y);134static void (*fp_gtk_paint_vline)(GtkStyle* style, GdkWindow* window,135GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,136const gchar* detail, gint y1, gint y2, gint x);137static void (*fp_gtk_paint_shadow)(GtkStyle* style, GdkWindow* window,138GtkStateType state_type, GtkShadowType shadow_type,139GdkRectangle* area, GtkWidget* widget, const gchar* detail,140gint x, gint y, gint width, gint height);141static void (*fp_gtk_paint_arrow)(GtkStyle* style, GdkWindow* window,142GtkStateType state_type, GtkShadowType shadow_type,143GdkRectangle* area, GtkWidget* widget, const gchar* detail,144GtkArrowType arrow_type, gboolean fill, gint x, gint y,145gint width, gint height);146static void (*fp_gtk_paint_diamond)(GtkStyle* style, GdkWindow* window,147GtkStateType state_type, GtkShadowType shadow_type,148GdkRectangle* area, GtkWidget* widget, const gchar* detail,149gint x, gint y, gint width, gint height);150static void (*fp_gtk_paint_box)(GtkStyle* style, GdkWindow* window,151GtkStateType state_type, GtkShadowType shadow_type,152GdkRectangle* area, GtkWidget* widget, const gchar* detail,153gint x, gint y, gint width, gint height);154static void (*fp_gtk_paint_flat_box)(GtkStyle* style, GdkWindow* window,155GtkStateType state_type, GtkShadowType shadow_type,156GdkRectangle* area, GtkWidget* widget, const gchar* detail,157gint x, gint y, gint width, gint height);158static void (*fp_gtk_paint_check)(GtkStyle* style, GdkWindow* window,159GtkStateType state_type, GtkShadowType shadow_type,160GdkRectangle* area, GtkWidget* widget, const gchar* detail,161gint x, gint y, gint width, gint height);162static void (*fp_gtk_paint_option)(GtkStyle* style, GdkWindow* window,163GtkStateType state_type, GtkShadowType shadow_type,164GdkRectangle* area, GtkWidget* widget, const gchar* detail,165gint x, gint y, gint width, gint height);166static void (*fp_gtk_paint_box_gap)(GtkStyle* style, GdkWindow* window,167GtkStateType state_type, GtkShadowType shadow_type,168GdkRectangle* area, GtkWidget* widget, const gchar* detail,169gint x, gint y, gint width, gint height,170GtkPositionType gap_side, gint gap_x, gint gap_width);171static void (*fp_gtk_paint_extension)(GtkStyle* style, GdkWindow* window,172GtkStateType state_type, GtkShadowType shadow_type,173GdkRectangle* area, GtkWidget* widget, const gchar* detail,174gint x, gint y, gint width, gint height, GtkPositionType gap_side);175static void (*fp_gtk_paint_focus)(GtkStyle* style, GdkWindow* window,176GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,177const gchar* detail, gint x, gint y, gint width, gint height);178static void (*fp_gtk_paint_slider)(GtkStyle* style, GdkWindow* window,179GtkStateType state_type, GtkShadowType shadow_type,180GdkRectangle* area, GtkWidget* widget, const gchar* detail,181gint x, gint y, gint width, gint height, GtkOrientation orientation);182static void (*fp_gtk_paint_handle)(GtkStyle* style, GdkWindow* window,183GtkStateType state_type, GtkShadowType shadow_type,184GdkRectangle* area, GtkWidget* widget, const gchar* detail,185gint x, gint y, gint width, gint height, GtkOrientation orientation);186static void (*fp_gtk_paint_expander)(GtkStyle* style, GdkWindow* window,187GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,188const gchar* detail, gint x, gint y, GtkExpanderStyle expander_style);189static void (*fp_gtk_style_apply_default_background)(GtkStyle* style,190GdkWindow* window, gboolean set_bg, GtkStateType state_type,191GdkRectangle* area, gint x, gint y, gint width, gint height);192193/* Widget creation */194static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type,195GtkShadowType shadow_type);196static GtkWidget* (*fp_gtk_button_new)();197static GtkWidget* (*fp_gtk_check_button_new)();198static GtkWidget* (*fp_gtk_check_menu_item_new)();199static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title);200static GtkWidget* (*fp_gtk_combo_box_new)();201static GtkWidget* (*fp_gtk_combo_box_entry_new)();202static GtkWidget* (*fp_gtk_entry_new)();203static GtkWidget* (*fp_gtk_fixed_new)();204static GtkWidget* (*fp_gtk_handle_box_new)();205static GtkWidget* (*fp_gtk_hpaned_new)();206static GtkWidget* (*fp_gtk_vpaned_new)();207static GtkWidget* (*fp_gtk_hscale_new)(GtkAdjustment* adjustment);208static GtkWidget* (*fp_gtk_vscale_new)(GtkAdjustment* adjustment);209static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment);210static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment);211static GtkWidget* (*fp_gtk_hseparator_new)();212static GtkWidget* (*fp_gtk_vseparator_new)();213static GtkWidget* (*fp_gtk_image_new)();214static GtkWidget* (*fp_gtk_label_new)(const gchar* str);215static GtkWidget* (*fp_gtk_menu_new)();216static GtkWidget* (*fp_gtk_menu_bar_new)();217static GtkWidget* (*fp_gtk_menu_item_new)();218static GtkWidget* (*fp_gtk_notebook_new)();219static GtkWidget* (*fp_gtk_progress_bar_new)();220static GtkWidget* (*fp_gtk_progress_bar_set_orientation)(221GtkProgressBar *pbar,222GtkProgressBarOrientation orientation);223static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group);224static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group);225static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment,226GtkAdjustment *vadjustment);227static GtkWidget* (*fp_gtk_separator_menu_item_new)();228static GtkWidget* (*fp_gtk_separator_tool_item_new)();229static GtkWidget* (*fp_gtk_text_view_new)();230static GtkWidget* (*fp_gtk_toggle_button_new)();231static GtkWidget* (*fp_gtk_toolbar_new)();232static GtkWidget* (*fp_gtk_tree_view_new)();233static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment,234GtkAdjustment *vadjustment);235static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type);236static GtkWidget* (*fp_gtk_dialog_new)();237static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment,238gdouble climb_rate, guint digits);239static GtkWidget* (*fp_gtk_frame_new)(const gchar *label);240241/* Other widget operations */242static GtkObject* (*fp_gtk_adjustment_new)(gdouble value,243gdouble lower, gdouble upper, gdouble step_increment,244gdouble page_increment, gdouble page_size);245static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget);246static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell,247GtkWidget *child);248static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item,249GtkWidget *submenu);250static void (*fp_gtk_widget_realize)(GtkWidget *widget);251static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget,252const gchar *stock_id, GtkIconSize size, const gchar *detail);253static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name);254static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent);255static void (*fp_gtk_widget_set_direction)(GtkWidget *widget,256GtkTextDirection direction);257static void (*fp_gtk_widget_style_get)(GtkWidget *widget,258const gchar *first_property_name, ...);259static void (*fp_gtk_widget_class_install_style_property)(260GtkWidgetClass* class, GParamSpec *pspec);261static GParamSpec* (*fp_gtk_widget_class_find_style_property)(262GtkWidgetClass* class, const gchar* property_name);263static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget,264const gchar* property_name, GValue* value);265static char* (*fp_pango_font_description_to_string)(266const PangoFontDescription* fd);267static GtkSettings* (*fp_gtk_settings_get_default)();268static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget);269static GType (*fp_gtk_border_get_type)();270static void (*fp_gtk_arrow_set)(GtkWidget* arrow,271GtkArrowType arrow_type,272GtkShadowType shadow_type);273static void (*fp_gtk_widget_size_request)(GtkWidget *widget,274GtkRequisition *requisition);275static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range);276277/* Method bodies */278279static void throw_exception(JNIEnv *env, const char* name, const char* message)280{281jclass class = (*env)->FindClass(env, name);282283if (class != NULL)284(*env)->ThrowNew(env, class, message);285286(*env)->DeleteLocalRef(env, class);287}288289/* This is a workaround for the bug:290* http://sourceware.org/bugzilla/show_bug.cgi?id=1814291* (dlsym/dlopen clears dlerror state)292* This bug is specific to Linux, but there is no harm in293* applying this workaround on Solaris as well.294*/295static void* dl_symbol(const char* name)296{297void* result = dlsym(gtk2_libhandle, name);298if (!result)299longjmp(j, NO_SYMBOL_EXCEPTION);300301return result;302}303304static void* dl_symbol_gthread(const char* name)305{306void* result = dlsym(gthread_libhandle, name);307if (!result)308longjmp(j, NO_SYMBOL_EXCEPTION);309310return result;311}312313gboolean gtk2_check(const char* lib_name, gboolean load)314{315if (gtk2_libhandle != NULL) {316/* We've already successfully opened the GTK libs, so return true. */317return TRUE;318} else {319void *lib = NULL;320#ifdef RTLD_NOLOAD321/* Just check if gtk libs are already in the process space */322lib = dlopen(lib_name, RTLD_LAZY | RTLD_NOLOAD);323if (!load || lib != NULL) {324return lib != NULL;325}326#else327#ifdef _AIX328/* On AIX we could implement this with the help of loadquery(L_GETINFO, ..) */329/* (see reload_table() in hotspot/src/os/aix/vm/loadlib_aix.cpp) but it is */330/* probably not worth it because most AIX servers don't have GTK libs anyway */331#endif332#endif333334lib = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);335336if (lib == NULL) {337return FALSE;338}339340fp_gtk_check_version = dlsym(lib, "gtk_check_version");341/* Check for GTK 2.2+ */342if (!fp_gtk_check_version(2, 2, 0)) {343return TRUE;344}345346// 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065347// dlclose(lib);348349return FALSE;350}351}352353#define ADD_SUPPORTED_ACTION(actionStr) \354do { \355jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, "Ljava/awt/Desktop$Action;"); \356if (!(*env)->ExceptionCheck(env)) { \357jobject action = (*env)->GetStaticObjectField(env, cls_action, fld_action); \358(*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, action); \359} else { \360(*env)->ExceptionClear(env); \361} \362} while(0);363364365static void update_supported_actions(JNIEnv *env) {366GVfs * (*fp_g_vfs_get_default) (void);367const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);368const gchar * const * schemes = NULL;369370jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action");371CHECK_NULL(cls_action);372jclass cls_xDesktopPeer = (*env)->FindClass(env, "sun/awt/X11/XDesktopPeer");373CHECK_NULL(cls_xDesktopPeer);374jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, cls_xDesktopPeer, "supportedActions", "Ljava/util/List;");375CHECK_NULL(fld_supportedActions);376jobject supportedActions = (*env)->GetStaticObjectField(env, cls_xDesktopPeer, fld_supportedActions);377378jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList");379CHECK_NULL(cls_arrayList);380jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", "(Ljava/lang/Object;)Z");381CHECK_NULL(mid_arrayListAdd);382jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, "clear", "()V");383CHECK_NULL(mid_arrayListClear);384385(*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear);386387ADD_SUPPORTED_ACTION("OPEN");388389/**390* gtk_show_uri() documentation says:391*392* > you need to install gvfs to get support for uri schemes such as http://393* > or ftp://, as only local files are handled by GIO itself.394*395* So OPEN action was safely added here.396* However, it looks like Solaris 11 have gvfs support only for 32-bit397* applications only by default.398*/399400fp_g_vfs_get_default = dl_symbol("g_vfs_get_default");401fp_g_vfs_get_supported_uri_schemes = dl_symbol("g_vfs_get_supported_uri_schemes");402dlerror();403404if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) {405GVfs * vfs = fp_g_vfs_get_default();406schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL;407if (schemes) {408int i = 0;409while (schemes[i]) {410if (strcmp(schemes[i], "http") == 0) {411ADD_SUPPORTED_ACTION("BROWSE");412ADD_SUPPORTED_ACTION("MAIL");413break;414}415i++;416}417}418} else {419#ifdef INTERNAL_BUILD420fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n");421#endif /* INTERNAL_BUILD */422}423424}425/**426* Functions for awt_Desktop.c427*/428static gboolean gtk2_show_uri_load(JNIEnv *env) {429gboolean success = FALSE;430dlerror();431const char *gtk_version = fp_gtk_check_version(2, 14, 0);432if (gtk_version != NULL) {433// The gtk_show_uri is available from GTK+ 2.14434#ifdef INTERNAL_BUILD435fprintf (stderr, "The version of GTK is %s. "436"The gtk_show_uri function is supported "437"since GTK+ 2.14.\n", gtk_version);438#endif /* INTERNAL_BUILD */439} else {440// Loading symbols only if the GTK version is 2.14 and higher441fp_gtk_show_uri = dl_symbol("gtk_show_uri");442const char *dlsym_error = dlerror();443if (dlsym_error) {444#ifdef INTERNAL_BUILD445fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error);446#endif /* INTERNAL_BUILD */447} else if (fp_gtk_show_uri == NULL) {448#ifdef INTERNAL_BUILD449fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");450#endif /* INTERNAL_BUILD */451} else {452gtk->gtk_show_uri = fp_gtk_show_uri;453update_supported_actions(env);454success = TRUE;455}456}457return success;458}459460/**461* Functions for sun_awt_X11_GtkFileDialogPeer.c462*/463static void gtk2_file_chooser_load()464{465fp_gtk_file_chooser_get_filename = dl_symbol(466"gtk_file_chooser_get_filename");467fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new");468fp_gtk_file_chooser_set_current_folder = dl_symbol(469"gtk_file_chooser_set_current_folder");470fp_gtk_file_chooser_set_filename = dl_symbol(471"gtk_file_chooser_set_filename");472fp_gtk_file_chooser_set_current_name = dl_symbol(473"gtk_file_chooser_set_current_name");474fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom");475fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");476fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");477fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");478if (fp_gtk_check_version(2, 8, 0) == NULL) {479fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(480"gtk_file_chooser_set_do_overwrite_confirmation");481}482fp_gtk_file_chooser_set_select_multiple = dl_symbol(483"gtk_file_chooser_set_select_multiple");484fp_gtk_file_chooser_get_current_folder = dl_symbol(485"gtk_file_chooser_get_current_folder");486fp_gtk_file_chooser_get_filenames = dl_symbol(487"gtk_file_chooser_get_filenames");488fp_gtk_g_slist_length = dl_symbol("g_slist_length");489}490491GtkApi* gtk2_load(JNIEnv *env, const char* lib_name)492{493gboolean result;494int i;495int (*handler)();496int (*io_handler)();497char *gtk_modules_env;498499gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);500if (gtk2_libhandle == NULL) {501return FALSE;502}503504gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);505if (gthread_libhandle == NULL) {506gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL);507if (gthread_libhandle == NULL)508return FALSE;509}510511if (setjmp(j) == 0)512{513fp_gtk_check_version = dl_symbol("gtk_check_version");514/* Check for GTK 2.2+ */515if (fp_gtk_check_version(2, 2, 0)) {516longjmp(j, NO_SYMBOL_EXCEPTION);517}518519/* GLib */520fp_glib_check_version = dlsym(gtk2_libhandle, "glib_check_version");521if (!fp_glib_check_version) {522dlerror();523}524fp_g_free = dl_symbol("g_free");525fp_g_object_unref = dl_symbol("g_object_unref");526527fp_g_main_context_iteration =528dl_symbol("g_main_context_iteration");529530fp_g_value_init = dl_symbol("g_value_init");531fp_g_type_is_a = dl_symbol("g_type_is_a");532533fp_g_value_get_boolean = dl_symbol("g_value_get_boolean");534fp_g_value_get_char = dl_symbol("g_value_get_char");535fp_g_value_get_uchar = dl_symbol("g_value_get_uchar");536fp_g_value_get_int = dl_symbol("g_value_get_int");537fp_g_value_get_uint = dl_symbol("g_value_get_uint");538fp_g_value_get_long = dl_symbol("g_value_get_long");539fp_g_value_get_ulong = dl_symbol("g_value_get_ulong");540fp_g_value_get_int64 = dl_symbol("g_value_get_int64");541fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64");542fp_g_value_get_float = dl_symbol("g_value_get_float");543fp_g_value_get_double = dl_symbol("g_value_get_double");544fp_g_value_get_string = dl_symbol("g_value_get_string");545fp_g_value_get_enum = dl_symbol("g_value_get_enum");546fp_g_value_get_flags = dl_symbol("g_value_get_flags");547fp_g_value_get_param = dl_symbol("g_value_get_param");548fp_g_value_get_boxed = dl_symbol("g_value_get_boxed");549fp_g_value_get_pointer = dl_symbol("g_value_get_pointer");550fp_g_value_get_object = dl_symbol("g_value_get_object");551fp_g_param_spec_int = dl_symbol("g_param_spec_int");552fp_g_object_get = dl_symbol("g_object_get");553fp_g_object_set = dl_symbol("g_object_set");554555/* GDK */556fp_gdk_pixmap_new = dl_symbol("gdk_pixmap_new");557fp_gdk_pixbuf_get_from_drawable =558dl_symbol("gdk_pixbuf_get_from_drawable");559fp_gdk_gc_new = dl_symbol("gdk_gc_new");560fp_gdk_rgb_gc_set_foreground =561dl_symbol("gdk_rgb_gc_set_foreground");562fp_gdk_draw_rectangle = dl_symbol("gdk_draw_rectangle");563fp_gdk_drawable_get_size = dl_symbol("gdk_drawable_get_size");564565/* Pixbuf */566fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new");567fp_gdk_pixbuf_new_from_file =568dl_symbol("gdk_pixbuf_new_from_file");569fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width");570fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height");571fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels");572fp_gdk_pixbuf_get_rowstride =573dl_symbol("gdk_pixbuf_get_rowstride");574fp_gdk_pixbuf_get_has_alpha =575dl_symbol("gdk_pixbuf_get_has_alpha");576fp_gdk_pixbuf_get_bits_per_sample =577dl_symbol("gdk_pixbuf_get_bits_per_sample");578fp_gdk_pixbuf_get_n_channels =579dl_symbol("gdk_pixbuf_get_n_channels");580581/* GTK painting */582fp_gtk_init_check = dl_symbol("gtk_init_check");583fp_gtk_paint_hline = dl_symbol("gtk_paint_hline");584fp_gtk_paint_vline = dl_symbol("gtk_paint_vline");585fp_gtk_paint_shadow = dl_symbol("gtk_paint_shadow");586fp_gtk_paint_arrow = dl_symbol("gtk_paint_arrow");587fp_gtk_paint_diamond = dl_symbol("gtk_paint_diamond");588fp_gtk_paint_box = dl_symbol("gtk_paint_box");589fp_gtk_paint_flat_box = dl_symbol("gtk_paint_flat_box");590fp_gtk_paint_check = dl_symbol("gtk_paint_check");591fp_gtk_paint_option = dl_symbol("gtk_paint_option");592fp_gtk_paint_box_gap = dl_symbol("gtk_paint_box_gap");593fp_gtk_paint_extension = dl_symbol("gtk_paint_extension");594fp_gtk_paint_focus = dl_symbol("gtk_paint_focus");595fp_gtk_paint_slider = dl_symbol("gtk_paint_slider");596fp_gtk_paint_handle = dl_symbol("gtk_paint_handle");597fp_gtk_paint_expander = dl_symbol("gtk_paint_expander");598fp_gtk_style_apply_default_background =599dl_symbol("gtk_style_apply_default_background");600601/* GTK widgets */602fp_gtk_arrow_new = dl_symbol("gtk_arrow_new");603fp_gtk_button_new = dl_symbol("gtk_button_new");604fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new");605fp_gtk_check_button_new = dl_symbol("gtk_check_button_new");606fp_gtk_check_menu_item_new =607dl_symbol("gtk_check_menu_item_new");608fp_gtk_color_selection_dialog_new =609dl_symbol("gtk_color_selection_dialog_new");610fp_gtk_entry_new = dl_symbol("gtk_entry_new");611fp_gtk_fixed_new = dl_symbol("gtk_fixed_new");612fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new");613fp_gtk_image_new = dl_symbol("gtk_image_new");614fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new");615fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new");616fp_gtk_hscale_new = dl_symbol("gtk_hscale_new");617fp_gtk_vscale_new = dl_symbol("gtk_vscale_new");618fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new");619fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new");620fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new");621fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new");622fp_gtk_label_new = dl_symbol("gtk_label_new");623fp_gtk_menu_new = dl_symbol("gtk_menu_new");624fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new");625fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new");626fp_gtk_menu_item_set_submenu =627dl_symbol("gtk_menu_item_set_submenu");628fp_gtk_notebook_new = dl_symbol("gtk_notebook_new");629fp_gtk_progress_bar_new =630dl_symbol("gtk_progress_bar_new");631fp_gtk_progress_bar_set_orientation =632dl_symbol("gtk_progress_bar_set_orientation");633fp_gtk_radio_button_new =634dl_symbol("gtk_radio_button_new");635fp_gtk_radio_menu_item_new =636dl_symbol("gtk_radio_menu_item_new");637fp_gtk_scrolled_window_new =638dl_symbol("gtk_scrolled_window_new");639fp_gtk_separator_menu_item_new =640dl_symbol("gtk_separator_menu_item_new");641fp_gtk_text_view_new = dl_symbol("gtk_text_view_new");642fp_gtk_toggle_button_new =643dl_symbol("gtk_toggle_button_new");644fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new");645fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new");646fp_gtk_viewport_new = dl_symbol("gtk_viewport_new");647fp_gtk_window_new = dl_symbol("gtk_window_new");648fp_gtk_window_present = dl_symbol("gtk_window_present");649fp_gtk_window_move = dl_symbol("gtk_window_move");650fp_gtk_window_resize = dl_symbol("gtk_window_resize");651652fp_gtk_dialog_new = dl_symbol("gtk_dialog_new");653fp_gtk_frame_new = dl_symbol("gtk_frame_new");654655fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new");656fp_gtk_container_add = dl_symbol("gtk_container_add");657fp_gtk_menu_shell_append =658dl_symbol("gtk_menu_shell_append");659fp_gtk_widget_realize = dl_symbol("gtk_widget_realize");660fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy");661fp_gtk_widget_render_icon =662dl_symbol("gtk_widget_render_icon");663fp_gtk_widget_set_name =664dl_symbol("gtk_widget_set_name");665fp_gtk_widget_set_parent =666dl_symbol("gtk_widget_set_parent");667fp_gtk_widget_set_direction =668dl_symbol("gtk_widget_set_direction");669fp_gtk_widget_style_get =670dl_symbol("gtk_widget_style_get");671fp_gtk_widget_class_install_style_property =672dl_symbol("gtk_widget_class_install_style_property");673fp_gtk_widget_class_find_style_property =674dl_symbol("gtk_widget_class_find_style_property");675fp_gtk_widget_style_get_property =676dl_symbol("gtk_widget_style_get_property");677fp_pango_font_description_to_string =678dl_symbol("pango_font_description_to_string");679fp_gtk_settings_get_default =680dl_symbol("gtk_settings_get_default");681fp_gtk_widget_get_settings =682dl_symbol("gtk_widget_get_settings");683fp_gtk_border_get_type = dl_symbol("gtk_border_get_type");684fp_gtk_arrow_set = dl_symbol("gtk_arrow_set");685fp_gtk_widget_size_request =686dl_symbol("gtk_widget_size_request");687fp_gtk_range_get_adjustment =688dl_symbol("gtk_range_get_adjustment");689690fp_gtk_widget_hide = dl_symbol("gtk_widget_hide");691fp_gtk_main_quit = dl_symbol("gtk_main_quit");692fp_g_signal_connect_data = dl_symbol("g_signal_connect_data");693fp_gtk_widget_show = dl_symbol("gtk_widget_show");694fp_gtk_main = dl_symbol("gtk_main");695696fp_g_path_get_dirname = dl_symbol("g_path_get_dirname");697698/**699* GLib thread system700*/701if (GLIB_CHECK_VERSION(2, 20, 0)) {702fp_g_thread_get_initialized = dl_symbol_gthread("g_thread_get_initialized");703}704fp_g_thread_init = dl_symbol_gthread("g_thread_init");705fp_gdk_threads_init = dl_symbol("gdk_threads_init");706fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");707fp_gdk_threads_leave = dl_symbol("gdk_threads_leave");708709/**710* Functions for sun_awt_X11_GtkFileDialogPeer.c711*/712if (fp_gtk_check_version(2, 4, 0) == NULL) {713// The current GtkFileChooser is available from GTK+ 2.4714gtk2_file_chooser_load();715}716717/* Some functions may be missing in pre-2.4 GTK.718We handle them specially here.719*/720fp_gtk_combo_box_new = dlsym(gtk2_libhandle, "gtk_combo_box_new");721if (fp_gtk_combo_box_new == NULL) {722fp_gtk_combo_box_new = dl_symbol("gtk_combo_new");723}724725fp_gtk_combo_box_entry_new =726dlsym(gtk2_libhandle, "gtk_combo_box_entry_new");727if (fp_gtk_combo_box_entry_new == NULL) {728fp_gtk_combo_box_entry_new = dl_symbol("gtk_combo_new");729new_combo = FALSE;730}731732fp_gtk_separator_tool_item_new =733dlsym(gtk2_libhandle, "gtk_separator_tool_item_new");734if (fp_gtk_separator_tool_item_new == NULL) {735fp_gtk_separator_tool_item_new =736dl_symbol("gtk_vseparator_new");737}738}739/* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION740* Otherwise we can check the return value of setjmp method.741*/742else743{744dlclose(gtk2_libhandle);745gtk2_libhandle = NULL;746747dlclose(gthread_libhandle);748gthread_libhandle = NULL;749750return FALSE;751}752753/*754* Strip the AT-SPI GTK_MODULES if present755*/756gtk_modules_env = getenv ("GTK_MODULES");757if ((gtk_modules_env && strstr(gtk_modules_env, "atk-bridge")) ||758(gtk_modules_env && strstr(gtk_modules_env, "gail"))) {759/* careful, strtok modifies its args */760gchar *tmp_env = strdup(gtk_modules_env);761if (tmp_env) {762/* the new env will be smaller than the old one */763gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc,764sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env));765766if (new_env) {767strcpy(new_env, ENV_PREFIX);768769/* strip out 'atk-bridge' and 'gail' */770size_t PREFIX_LENGTH = strlen(ENV_PREFIX);771gchar *tmp_ptr = NULL;772for (s = strtok_r(tmp_env, ":", &tmp_ptr); s;773s = strtok_r(NULL, ":", &tmp_ptr)) {774if ((!strstr(s, "atk-bridge")) && (!strstr(s, "gail"))) {775if (strlen(new_env) > PREFIX_LENGTH) {776new_env = strcat(new_env, ":");777}778new_env = strcat(new_env, s);779}780}781if (putenv(new_env) != 0) {782/* no free() on success, putenv() doesn't copy string */783free(new_env);784}785}786free(tmp_env);787}788}789/*790* GTK should be initialized with gtk_init_check() before use.791*792* gtk_init_check installs its own error handlers. It is critical that793* we preserve error handler set from AWT. Otherwise we'll crash on794* BadMatch errors which we would normally ignore. The IO error handler795* is preserved here, too, just for consistency.796*/797AWT_LOCK();798handler = XSetErrorHandler(NULL);799io_handler = XSetIOErrorHandler(NULL);800801if (fp_gtk_check_version(2, 2, 0) == NULL) {802jclass clazz = (*env)->FindClass(env, "sun/misc/GThreadHelper");803jmethodID mid_getAndSetInitializationNeededFlag =804(*env)->GetStaticMethodID(env, clazz, "getAndSetInitializationNeededFlag", "()Z");805jmethodID mid_lock = (*env)->GetStaticMethodID(env, clazz, "lock", "()V");806jmethodID mid_unlock = (*env)->GetStaticMethodID(env, clazz, "unlock", "()V");807808// Init the thread system to use GLib in a thread-safe mode809(*env)->CallStaticVoidMethod(env, clazz, mid_lock);810811// Calling g_thread_init() multiple times leads to crash on GLib < 2.24812// We can use g_thread_get_initialized () but it is available only for813// GLib >= 2.20. We rely on GThreadHelper for GLib < 2.20.814gboolean is_g_thread_get_initialized = FALSE;815if (GLIB_CHECK_VERSION(2, 20, 0)) {816is_g_thread_get_initialized = fp_g_thread_get_initialized();817}818819if (!(*env)->CallStaticBooleanMethod(env, clazz, mid_getAndSetInitializationNeededFlag)) {820if (!is_g_thread_get_initialized) {821fp_g_thread_init(NULL);822}823824//According the GTK documentation, gdk_threads_init() should be825//called before gtk_init() or gtk_init_check()826fp_gdk_threads_init();827}828(*env)->CallStaticVoidMethod(env, clazz, mid_unlock);829}830result = (*fp_gtk_init_check)(NULL, NULL);831832XSetErrorHandler(handler);833XSetIOErrorHandler(io_handler);834AWT_UNLOCK();835836/* Initialize widget array. */837for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)838{839gtk2_widgets[i] = NULL;840}841842if (result) {843GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi));844gtk2_init(gtk);845return gtk;846}847return NULL;848}849850int gtk2_unload()851{852int i;853char *gtk2_error;854855if (!gtk2_libhandle)856return TRUE;857858/* Release painting objects */859if (gtk2_white_pixmap != NULL) {860(*fp_g_object_unref)(gtk2_white_pixmap);861(*fp_g_object_unref)(gtk2_black_pixmap);862(*fp_g_object_unref)(gtk2_white_pixbuf);863(*fp_g_object_unref)(gtk2_black_pixbuf);864gtk2_white_pixmap = gtk2_black_pixmap =865gtk2_white_pixbuf = gtk2_black_pixbuf = NULL;866}867gtk2_pixbuf_width = 0;868gtk2_pixbuf_height = 0;869870if (gtk2_window != NULL) {871/* Destroying toplevel widget will destroy all contained widgets */872(*fp_gtk_widget_destroy)(gtk2_window);873874/* Unset some static data so they get reinitialized on next load */875gtk2_window = NULL;876}877878dlerror();879dlclose(gtk2_libhandle);880dlclose(gthread_libhandle);881if ((gtk2_error = dlerror()) != NULL)882{883return FALSE;884}885return TRUE;886}887888/* Dispatch all pending events from the GTK event loop.889* This is needed to catch theme change and update widgets' style.890*/891static void flush_gtk_event_loop()892{893while( (*fp_g_main_context_iteration)(NULL, FALSE));894}895896/*897* Initialize components of containment hierarchy. This creates a GtkFixed898* inside a GtkWindow. All widgets get realized.899*/900static void init_containers()901{902if (gtk2_window == NULL)903{904gtk2_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);905gtk2_fixed = (GtkFixed *)(*fp_gtk_fixed_new)();906(*fp_gtk_container_add)((GtkContainer*)gtk2_window,907(GtkWidget *)gtk2_fixed);908(*fp_gtk_widget_realize)(gtk2_window);909(*fp_gtk_widget_realize)((GtkWidget *)gtk2_fixed);910}911}912913/*914* Ensure everything is ready for drawing an element of the specified width915* and height.916*917* We should somehow handle translucent images. GTK can draw to X Drawables918* only, which don't support alpha. When we retrieve the image back from919* the server, translucency information is lost. There're several ways to920* work around this:921* 1) Subclass GdkPixmap and cache translucent objects on client side. This922* requires us to implement parts of X server drawing logic on client side.923* Many X requests can potentially be "translucent"; e.g. XDrawLine with924* fill=tile and a translucent tile is a "translucent" operation, whereas925* XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some926* do) intermix transparent and opaque operations which makes caching even927* more problematic.928* 2) Use Xorg 32bit ARGB visual when available. GDK has no native support929* for it (as of version 2.6). Also even in JDS 3 Xorg does not support930* these visuals by default, which makes optimizing for them pointless.931* We can consider doing this at a later point when ARGB visuals become more932* popular.933* 3') GTK has plans to use Cairo as its graphical backend (presumably in934* 2.8), and Cairo supports alpha. With it we could also get rid of the935* unnecessary round trip to server and do all the drawing on client side.936* 4) For now we draw to two different pixmaps and restore alpha channel by937* comparing results. This can be optimized by using subclassed pixmap and938* doing the second drawing only if necessary.939*/940static void gtk2_init_painting(JNIEnv *env, gint width, gint height)941{942GdkGC *gc;943GdkPixbuf *white, *black;944945init_containers();946947if (gtk2_pixbuf_width < width || gtk2_pixbuf_height < height)948{949white = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);950black = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);951952if (white == NULL || black == NULL)953{954snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height);955throw_exception(env, "java/lang/RuntimeException", convertionBuffer);956fp_gdk_threads_leave();957return;958}959960if (gtk2_white_pixmap != NULL) {961/* free old stuff */962(*fp_g_object_unref)(gtk2_white_pixmap);963(*fp_g_object_unref)(gtk2_black_pixmap);964(*fp_g_object_unref)(gtk2_white_pixbuf);965(*fp_g_object_unref)(gtk2_black_pixbuf);966}967968gtk2_white_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1);969gtk2_black_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1);970971gtk2_white_pixbuf = white;972gtk2_black_pixbuf = black;973974gtk2_pixbuf_width = width;975gtk2_pixbuf_height = height;976}977978/* clear the pixmaps */979gc = (*fp_gdk_gc_new)(gtk2_white_pixmap);980(*fp_gdk_rgb_gc_set_foreground)(gc, 0xffffff);981(*fp_gdk_draw_rectangle)(gtk2_white_pixmap, gc, TRUE, 0, 0, width, height);982(*fp_g_object_unref)(gc);983984gc = (*fp_gdk_gc_new)(gtk2_black_pixmap);985(*fp_gdk_rgb_gc_set_foreground)(gc, 0x000000);986(*fp_gdk_draw_rectangle)(gtk2_black_pixmap, gc, TRUE, 0, 0, width, height);987(*fp_g_object_unref)(gc);988}989990/*991* Restore image from white and black pixmaps and copy it into destination992* buffer. This method compares two pixbufs taken from white and black993* pixmaps and decodes color and alpha components. Pixbufs are RGB without994* alpha, destination buffer is ABGR.995*996* The return value is the transparency type of the resulting image, either997* one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and998* java_awt_Transparency_TRANSLUCENT.999*/1000static gint gtk2_copy_image(gint *dst, gint width, gint height)1001{1002gint i, j, r, g, b;1003guchar *white, *black;1004gint stride, padding;1005gboolean is_opaque = TRUE;1006gboolean is_bitmask = TRUE;10071008(*fp_gdk_pixbuf_get_from_drawable)(gtk2_white_pixbuf, gtk2_white_pixmap,1009NULL, 0, 0, 0, 0, width, height);1010(*fp_gdk_pixbuf_get_from_drawable)(gtk2_black_pixbuf, gtk2_black_pixmap,1011NULL, 0, 0, 0, 0, width, height);10121013white = (*fp_gdk_pixbuf_get_pixels)(gtk2_white_pixbuf);1014black = (*fp_gdk_pixbuf_get_pixels)(gtk2_black_pixbuf);1015stride = (*fp_gdk_pixbuf_get_rowstride)(gtk2_black_pixbuf);1016padding = stride - width * 4;1017if (padding >= 0 && stride > 0) {1018for (i = 0; i < height; i++) {1019for (j = 0; j < width; j++) {1020int r1 = *white++;1021int r2 = *black++;1022int alpha = 0xff + r2 - r1;10231024switch (alpha) {1025case 0: /* transparent pixel */1026r = g = b = 0;1027black += 3;1028white += 3;1029is_opaque = FALSE;1030break;10311032case 0xff: /* opaque pixel */1033r = r2;1034g = *black++;1035b = *black++;1036black++;1037white += 3;1038break;10391040default: /* translucent pixel */1041r = 0xff * r2 / alpha;1042g = 0xff * *black++ / alpha;1043b = 0xff * *black++ / alpha;1044black++;1045white += 3;1046is_opaque = FALSE;1047is_bitmask = FALSE;1048break;1049}10501051*dst++ = (alpha << 24 | r << 16 | g << 8 | b);1052}10531054white += padding;1055black += padding;1056}1057}1058return is_opaque ? java_awt_Transparency_OPAQUE :1059(is_bitmask ? java_awt_Transparency_BITMASK :1060java_awt_Transparency_TRANSLUCENT);1061}10621063static void1064gtk2_set_direction(GtkWidget *widget, GtkTextDirection dir)1065{1066/*1067* Some engines (inexplicably) look at the direction of the widget's1068* parent, so we need to set the direction of both the widget and its1069* parent.1070*/1071(*fp_gtk_widget_set_direction)(widget, dir);1072if (widget->parent != NULL) {1073(*fp_gtk_widget_set_direction)(widget->parent, dir);1074}1075}10761077/*1078* Initializes the widget to correct state for some engines.1079* This is a pure empirical method.1080*/1081static void init_toggle_widget(WidgetType widget_type, gint synth_state)1082{1083gboolean is_active = ((synth_state & SELECTED) != 0);10841085if (widget_type == RADIO_BUTTON ||1086widget_type == CHECK_BOX ||1087widget_type == TOGGLE_BUTTON) {1088((GtkToggleButton*)gtk2_widget)->active = is_active;1089}10901091if ((synth_state & FOCUSED) != 0) {1092((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;1093} else {1094((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;1095}10961097if ((synth_state & MOUSE_OVER) != 0 && (synth_state & PRESSED) == 0 ||1098(synth_state & FOCUSED) != 0 && (synth_state & PRESSED) != 0) {1099gtk2_widget->state = GTK_STATE_PRELIGHT;1100} else if ((synth_state & DISABLED) != 0) {1101gtk2_widget->state = GTK_STATE_INSENSITIVE;1102} else {1103gtk2_widget->state = is_active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL;1104}1105}11061107/* GTK state_type filter */1108static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state)1109{1110GtkStateType result = GTK_STATE_NORMAL;11111112if ((synth_state & DISABLED) != 0) {1113result = GTK_STATE_INSENSITIVE;1114} else if ((synth_state & PRESSED) != 0) {1115result = GTK_STATE_ACTIVE;1116} else if ((synth_state & MOUSE_OVER) != 0) {1117result = GTK_STATE_PRELIGHT;1118}1119return result;1120}11211122/* GTK shadow_type filter */1123static GtkShadowType get_gtk_shadow_type(WidgetType widget_type, gint synth_state)1124{1125GtkShadowType result = GTK_SHADOW_OUT;11261127if ((synth_state & SELECTED) != 0) {1128result = GTK_SHADOW_IN;1129}1130return result;1131}113211331134static GtkWidget* gtk2_get_arrow(GtkArrowType arrow_type, GtkShadowType shadow_type)1135{1136GtkWidget *arrow = NULL;1137if (NULL == gtk2_widgets[_GTK_ARROW_TYPE])1138{1139gtk2_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type, shadow_type);1140(*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, gtk2_widgets[_GTK_ARROW_TYPE]);1141(*fp_gtk_widget_realize)(gtk2_widgets[_GTK_ARROW_TYPE]);1142}1143arrow = gtk2_widgets[_GTK_ARROW_TYPE];11441145(*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type);1146return arrow;1147}11481149static GtkAdjustment* create_adjustment()1150{1151return (GtkAdjustment *)1152(*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0);1153}11541155/**1156* Returns a pointer to the cached native widget for the specified widget1157* type.1158*/1159static GtkWidget *gtk2_get_widget(WidgetType widget_type)1160{1161gboolean init_result = FALSE;1162GtkWidget *result = NULL;1163switch (widget_type)1164{1165case BUTTON:1166case TABLE_HEADER:1167if (init_result = (NULL == gtk2_widgets[_GTK_BUTTON_TYPE]))1168{1169gtk2_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)();1170}1171result = gtk2_widgets[_GTK_BUTTON_TYPE];1172break;1173case CHECK_BOX:1174if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_BUTTON_TYPE]))1175{1176gtk2_widgets[_GTK_CHECK_BUTTON_TYPE] =1177(*fp_gtk_check_button_new)();1178}1179result = gtk2_widgets[_GTK_CHECK_BUTTON_TYPE];1180break;1181case CHECK_BOX_MENU_ITEM:1182if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE]))1183{1184gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE] =1185(*fp_gtk_check_menu_item_new)();1186}1187result = gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE];1188break;1189/************************************************************1190* Creation a dedicated color chooser is dangerous because1191* it deadlocks the EDT1192************************************************************/1193/* case COLOR_CHOOSER:1194if (init_result =1195(NULL == gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]))1196{1197gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] =1198(*fp_gtk_color_selection_dialog_new)(NULL);1199}1200result = gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE];1201break;*/1202case COMBO_BOX:1203if (init_result = (NULL == gtk2_widgets[_GTK_COMBO_BOX_TYPE]))1204{1205gtk2_widgets[_GTK_COMBO_BOX_TYPE] =1206(*fp_gtk_combo_box_new)();1207}1208result = gtk2_widgets[_GTK_COMBO_BOX_TYPE];1209break;1210case COMBO_BOX_ARROW_BUTTON:1211if (init_result =1212(NULL == gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]))1213{1214gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] =1215(*fp_gtk_toggle_button_new)();1216}1217result = gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE];1218break;1219case COMBO_BOX_TEXT_FIELD:1220if (init_result =1221(NULL == gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]))1222{1223result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] =1224(*fp_gtk_entry_new)();1225}1226result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE];1227break;1228case DESKTOP_ICON:1229case INTERNAL_FRAME_TITLE_PANE:1230case LABEL:1231if (init_result = (NULL == gtk2_widgets[_GTK_LABEL_TYPE]))1232{1233gtk2_widgets[_GTK_LABEL_TYPE] =1234(*fp_gtk_label_new)(NULL);1235}1236result = gtk2_widgets[_GTK_LABEL_TYPE];1237break;1238case DESKTOP_PANE:1239case PANEL:1240case ROOT_PANE:1241if (init_result = (NULL == gtk2_widgets[_GTK_CONTAINER_TYPE]))1242{1243/* There is no constructor for a container type. I've1244* chosen GtkFixed container since it has a default1245* constructor.1246*/1247gtk2_widgets[_GTK_CONTAINER_TYPE] =1248(*fp_gtk_fixed_new)();1249}1250result = gtk2_widgets[_GTK_CONTAINER_TYPE];1251break;1252case EDITOR_PANE:1253case TEXT_AREA:1254case TEXT_PANE:1255if (init_result = (NULL == gtk2_widgets[_GTK_TEXT_VIEW_TYPE]))1256{1257gtk2_widgets[_GTK_TEXT_VIEW_TYPE] =1258(*fp_gtk_text_view_new)();1259}1260result = gtk2_widgets[_GTK_TEXT_VIEW_TYPE];1261break;1262case FORMATTED_TEXT_FIELD:1263case PASSWORD_FIELD:1264case TEXT_FIELD:1265if (init_result = (NULL == gtk2_widgets[_GTK_ENTRY_TYPE]))1266{1267gtk2_widgets[_GTK_ENTRY_TYPE] =1268(*fp_gtk_entry_new)();1269}1270result = gtk2_widgets[_GTK_ENTRY_TYPE];1271break;1272case HANDLE_BOX:1273if (init_result = (NULL == gtk2_widgets[_GTK_HANDLE_BOX_TYPE]))1274{1275gtk2_widgets[_GTK_HANDLE_BOX_TYPE] =1276(*fp_gtk_handle_box_new)();1277}1278result = gtk2_widgets[_GTK_HANDLE_BOX_TYPE];1279break;1280case HSCROLL_BAR:1281case HSCROLL_BAR_BUTTON_LEFT:1282case HSCROLL_BAR_BUTTON_RIGHT:1283case HSCROLL_BAR_TRACK:1284case HSCROLL_BAR_THUMB:1285if (init_result = (NULL == gtk2_widgets[_GTK_HSCROLLBAR_TYPE]))1286{1287gtk2_widgets[_GTK_HSCROLLBAR_TYPE] =1288(*fp_gtk_hscrollbar_new)(create_adjustment());1289}1290result = gtk2_widgets[_GTK_HSCROLLBAR_TYPE];1291break;1292case HSEPARATOR:1293if (init_result = (NULL == gtk2_widgets[_GTK_HSEPARATOR_TYPE]))1294{1295gtk2_widgets[_GTK_HSEPARATOR_TYPE] =1296(*fp_gtk_hseparator_new)();1297}1298result = gtk2_widgets[_GTK_HSEPARATOR_TYPE];1299break;1300case HSLIDER:1301case HSLIDER_THUMB:1302case HSLIDER_TRACK:1303if (init_result = (NULL == gtk2_widgets[_GTK_HSCALE_TYPE]))1304{1305gtk2_widgets[_GTK_HSCALE_TYPE] =1306(*fp_gtk_hscale_new)(NULL);1307}1308result = gtk2_widgets[_GTK_HSCALE_TYPE];1309break;1310case HSPLIT_PANE_DIVIDER:1311case SPLIT_PANE:1312if (init_result = (NULL == gtk2_widgets[_GTK_HPANED_TYPE]))1313{1314gtk2_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)();1315}1316result = gtk2_widgets[_GTK_HPANED_TYPE];1317break;1318case IMAGE:1319if (init_result = (NULL == gtk2_widgets[_GTK_IMAGE_TYPE]))1320{1321gtk2_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)();1322}1323result = gtk2_widgets[_GTK_IMAGE_TYPE];1324break;1325case INTERNAL_FRAME:1326if (init_result = (NULL == gtk2_widgets[_GTK_WINDOW_TYPE]))1327{1328gtk2_widgets[_GTK_WINDOW_TYPE] =1329(*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);1330}1331result = gtk2_widgets[_GTK_WINDOW_TYPE];1332break;1333case TOOL_TIP:1334if (init_result = (NULL == gtk2_widgets[_GTK_TOOLTIP_TYPE]))1335{1336result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);1337(*fp_gtk_widget_set_name)(result, "gtk-tooltips");1338gtk2_widgets[_GTK_TOOLTIP_TYPE] = result;1339}1340result = gtk2_widgets[_GTK_TOOLTIP_TYPE];1341break;1342case LIST:1343case TABLE:1344case TREE:1345case TREE_CELL:1346if (init_result = (NULL == gtk2_widgets[_GTK_TREE_VIEW_TYPE]))1347{1348gtk2_widgets[_GTK_TREE_VIEW_TYPE] =1349(*fp_gtk_tree_view_new)();1350}1351result = gtk2_widgets[_GTK_TREE_VIEW_TYPE];1352break;1353case TITLED_BORDER:1354if (init_result = (NULL == gtk2_widgets[_GTK_FRAME_TYPE]))1355{1356gtk2_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL);1357}1358result = gtk2_widgets[_GTK_FRAME_TYPE];1359break;1360case POPUP_MENU:1361if (init_result = (NULL == gtk2_widgets[_GTK_MENU_TYPE]))1362{1363gtk2_widgets[_GTK_MENU_TYPE] =1364(*fp_gtk_menu_new)();1365}1366result = gtk2_widgets[_GTK_MENU_TYPE];1367break;1368case MENU:1369case MENU_ITEM:1370case MENU_ITEM_ACCELERATOR:1371if (init_result = (NULL == gtk2_widgets[_GTK_MENU_ITEM_TYPE]))1372{1373gtk2_widgets[_GTK_MENU_ITEM_TYPE] =1374(*fp_gtk_menu_item_new)();1375}1376result = gtk2_widgets[_GTK_MENU_ITEM_TYPE];1377break;1378case MENU_BAR:1379if (init_result = (NULL == gtk2_widgets[_GTK_MENU_BAR_TYPE]))1380{1381gtk2_widgets[_GTK_MENU_BAR_TYPE] =1382(*fp_gtk_menu_bar_new)();1383}1384result = gtk2_widgets[_GTK_MENU_BAR_TYPE];1385break;1386case COLOR_CHOOSER:1387case OPTION_PANE:1388if (init_result = (NULL == gtk2_widgets[_GTK_DIALOG_TYPE]))1389{1390gtk2_widgets[_GTK_DIALOG_TYPE] =1391(*fp_gtk_dialog_new)();1392}1393result = gtk2_widgets[_GTK_DIALOG_TYPE];1394break;1395case POPUP_MENU_SEPARATOR:1396if (init_result =1397(NULL == gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]))1398{1399gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] =1400(*fp_gtk_separator_menu_item_new)();1401}1402result = gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE];1403break;1404case HPROGRESS_BAR:1405if (init_result = (NULL == gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE]))1406{1407gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE] =1408(*fp_gtk_progress_bar_new)();1409}1410result = gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE];1411break;1412case VPROGRESS_BAR:1413if (init_result = (NULL == gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE]))1414{1415gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE] =1416(*fp_gtk_progress_bar_new)();1417/*1418* Vertical JProgressBars always go bottom-to-top,1419* regardless of the ComponentOrientation.1420*/1421(*fp_gtk_progress_bar_set_orientation)(1422(GtkProgressBar *)gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE],1423GTK_PROGRESS_BOTTOM_TO_TOP);1424}1425result = gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE];1426break;1427case RADIO_BUTTON:1428if (init_result = (NULL == gtk2_widgets[_GTK_RADIO_BUTTON_TYPE]))1429{1430gtk2_widgets[_GTK_RADIO_BUTTON_TYPE] =1431(*fp_gtk_radio_button_new)(NULL);1432}1433result = gtk2_widgets[_GTK_RADIO_BUTTON_TYPE];1434break;1435case RADIO_BUTTON_MENU_ITEM:1436if (init_result =1437(NULL == gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE]))1438{1439gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE] =1440(*fp_gtk_radio_menu_item_new)(NULL);1441}1442result = gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE];1443break;1444case SCROLL_PANE:1445if (init_result =1446(NULL == gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE]))1447{1448gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE] =1449(*fp_gtk_scrolled_window_new)(NULL, NULL);1450}1451result = gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE];1452break;1453case SPINNER:1454case SPINNER_ARROW_BUTTON:1455case SPINNER_TEXT_FIELD:1456if (init_result = (NULL == gtk2_widgets[_GTK_SPIN_BUTTON_TYPE]))1457{1458result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE] =1459(*fp_gtk_spin_button_new)(NULL, 0, 0);1460}1461result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE];1462break;1463case TABBED_PANE:1464case TABBED_PANE_TAB_AREA:1465case TABBED_PANE_CONTENT:1466case TABBED_PANE_TAB:1467if (init_result = (NULL == gtk2_widgets[_GTK_NOTEBOOK_TYPE]))1468{1469gtk2_widgets[_GTK_NOTEBOOK_TYPE] =1470(*fp_gtk_notebook_new)(NULL);1471}1472result = gtk2_widgets[_GTK_NOTEBOOK_TYPE];1473break;1474case TOGGLE_BUTTON:1475if (init_result = (NULL == gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE]))1476{1477gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE] =1478(*fp_gtk_toggle_button_new)(NULL);1479}1480result = gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE];1481break;1482case TOOL_BAR:1483case TOOL_BAR_DRAG_WINDOW:1484if (init_result = (NULL == gtk2_widgets[_GTK_TOOLBAR_TYPE]))1485{1486gtk2_widgets[_GTK_TOOLBAR_TYPE] =1487(*fp_gtk_toolbar_new)(NULL);1488}1489result = gtk2_widgets[_GTK_TOOLBAR_TYPE];1490break;1491case TOOL_BAR_SEPARATOR:1492if (init_result =1493(NULL == gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]))1494{1495gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] =1496(*fp_gtk_separator_tool_item_new)();1497}1498result = gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE];1499break;1500case VIEWPORT:1501if (init_result = (NULL == gtk2_widgets[_GTK_VIEWPORT_TYPE]))1502{1503GtkAdjustment *adjustment = create_adjustment();1504gtk2_widgets[_GTK_VIEWPORT_TYPE] =1505(*fp_gtk_viewport_new)(adjustment, adjustment);1506}1507result = gtk2_widgets[_GTK_VIEWPORT_TYPE];1508break;1509case VSCROLL_BAR:1510case VSCROLL_BAR_BUTTON_UP:1511case VSCROLL_BAR_BUTTON_DOWN:1512case VSCROLL_BAR_TRACK:1513case VSCROLL_BAR_THUMB:1514if (init_result = (NULL == gtk2_widgets[_GTK_VSCROLLBAR_TYPE]))1515{1516gtk2_widgets[_GTK_VSCROLLBAR_TYPE] =1517(*fp_gtk_vscrollbar_new)(create_adjustment());1518}1519result = gtk2_widgets[_GTK_VSCROLLBAR_TYPE];1520break;1521case VSEPARATOR:1522if (init_result = (NULL == gtk2_widgets[_GTK_VSEPARATOR_TYPE]))1523{1524gtk2_widgets[_GTK_VSEPARATOR_TYPE] =1525(*fp_gtk_vseparator_new)();1526}1527result = gtk2_widgets[_GTK_VSEPARATOR_TYPE];1528break;1529case VSLIDER:1530case VSLIDER_THUMB:1531case VSLIDER_TRACK:1532if (init_result = (NULL == gtk2_widgets[_GTK_VSCALE_TYPE]))1533{1534gtk2_widgets[_GTK_VSCALE_TYPE] =1535(*fp_gtk_vscale_new)(NULL);1536}1537result = gtk2_widgets[_GTK_VSCALE_TYPE];1538/*1539* Vertical JSliders start at the bottom, while vertical1540* GtkVScale widgets start at the top (by default), so to fix1541* this we set the "inverted" flag to get the Swing behavior.1542*/1543((GtkRange*)result)->inverted = 1;1544break;1545case VSPLIT_PANE_DIVIDER:1546if (init_result = (NULL == gtk2_widgets[_GTK_VPANED_TYPE]))1547{1548gtk2_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)();1549}1550result = gtk2_widgets[_GTK_VPANED_TYPE];1551break;1552default:1553result = NULL;1554break;1555}15561557if (result != NULL && init_result)1558{1559if (widget_type == RADIO_BUTTON_MENU_ITEM ||1560widget_type == CHECK_BOX_MENU_ITEM ||1561widget_type == MENU_ITEM ||1562widget_type == MENU ||1563widget_type == POPUP_MENU_SEPARATOR)1564{1565GtkWidget *menu = gtk2_get_widget(POPUP_MENU);1566(*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result);1567}1568else if (widget_type == POPUP_MENU)1569{1570GtkWidget *menu_bar = gtk2_get_widget(MENU_BAR);1571GtkWidget *root_menu = (*fp_gtk_menu_item_new)();1572(*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result);1573(*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu);1574}1575else if (widget_type == COMBO_BOX_ARROW_BUTTON ||1576widget_type == COMBO_BOX_TEXT_FIELD)1577{1578/*1579* We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry1580* in order to trick engines into thinking it's a real combobox1581* arrow button/text field.1582*/1583GtkWidget *combo = (*fp_gtk_combo_box_entry_new)();15841585if (new_combo && widget_type == COMBO_BOX_ARROW_BUTTON) {1586(*fp_gtk_widget_set_parent)(result, combo);1587((GtkBin*)combo)->child = result;1588} else {1589(*fp_gtk_container_add)((GtkContainer *)combo, result);1590}1591(*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, combo);1592}1593else if (widget_type != TOOL_TIP &&1594widget_type != INTERNAL_FRAME &&1595widget_type != OPTION_PANE)1596{1597(*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, result);1598}1599(*fp_gtk_widget_realize)(result);1600}1601return result;1602}16031604void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type,1605GtkShadowType shadow_type, const gchar *detail,1606gint x, gint y, gint width, gint height,1607GtkArrowType arrow_type, gboolean fill)1608{1609static int w, h;1610static GtkRequisition size;16111612if (widget_type == COMBO_BOX_ARROW_BUTTON || widget_type == TABLE)1613gtk2_widget = gtk2_get_arrow(arrow_type, shadow_type);1614else1615gtk2_widget = gtk2_get_widget(widget_type);16161617switch (widget_type)1618{1619case SPINNER_ARROW_BUTTON:1620x = 1;1621y = ((arrow_type == GTK_ARROW_UP) ? 2 : 0);1622height -= 2;1623width -= 3;16241625w = width / 2;1626w -= w % 2 - 1;1627h = (w + 1) / 2;1628break;16291630case HSCROLL_BAR_BUTTON_LEFT:1631case HSCROLL_BAR_BUTTON_RIGHT:1632case VSCROLL_BAR_BUTTON_UP:1633case VSCROLL_BAR_BUTTON_DOWN:1634w = width / 2;1635h = height / 2;1636break;16371638case COMBO_BOX_ARROW_BUTTON:1639case TABLE:1640x = 1;1641(*fp_gtk_widget_size_request)(gtk2_widget, &size);1642w = size.width - ((GtkMisc*)gtk2_widget)->xpad * 2;1643h = size.height - ((GtkMisc*)gtk2_widget)->ypad * 2;1644w = h = MIN(MIN(w, h), MIN(width,height)) * 0.7;1645break;16461647default:1648w = width;1649h = height;1650break;1651}1652x += (width - w) / 2;1653y += (height - h) / 2;16541655(*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_white_pixmap, state_type,1656shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,1657x, y, w, h);1658(*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_black_pixmap, state_type,1659shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,1660x, y, w, h);1661}16621663static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,1664GtkShadowType shadow_type, const gchar *detail,1665gint x, gint y, gint width, gint height,1666gint synth_state, GtkTextDirection dir)1667{1668gtk2_widget = gtk2_get_widget(widget_type);16691670/*1671* The clearlooks engine sometimes looks at the widget's state field1672* instead of just the state_type variable that we pass in, so to account1673* for those cases we set the widget's state field accordingly. The1674* flags field is similarly important for things like focus/default state.1675*/1676gtk2_widget->state = state_type;16771678if (widget_type == HSLIDER_TRACK) {1679/*1680* For horizontal JSliders with right-to-left orientation, we need1681* to set the "inverted" flag to match the native GTK behavior where1682* the foreground highlight is on the right side of the slider thumb.1683* This is needed especially for the ubuntulooks engine, which looks1684* exclusively at the "inverted" flag to determine on which side of1685* the thumb to paint the highlight...1686*/1687((GtkRange*)gtk2_widget)->inverted = (dir == GTK_TEXT_DIR_RTL);16881689/*1690* Note however that other engines like clearlooks will look at both1691* the "inverted" field and the text direction to determine how1692* the foreground highlight is painted:1693* !inverted && ltr --> paint highlight on left side1694* !inverted && rtl --> paint highlight on right side1695* inverted && ltr --> paint highlight on right side1696* inverted && rtl --> paint highlight on left side1697* So the only way to reliably get the desired results for horizontal1698* JSlider (i.e., highlight on left side for LTR ComponentOrientation1699* and highlight on right side for RTL ComponentOrientation) is to1700* always override text direction as LTR, and then set the "inverted"1701* flag accordingly (as we have done above).1702*/1703dir = GTK_TEXT_DIR_LTR;1704}17051706/*1707* Some engines (e.g. clearlooks) will paint the shadow of certain1708* widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the1709* the text direction.1710*/1711gtk2_set_direction(gtk2_widget, dir);17121713switch (widget_type) {1714case BUTTON:1715if (synth_state & DEFAULT) {1716((GtkObject*)gtk2_widget)->flags |= GTK_HAS_DEFAULT;1717} else {1718((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_DEFAULT;1719}1720break;1721case TOGGLE_BUTTON:1722init_toggle_widget(widget_type, synth_state);1723break;1724case HSCROLL_BAR_BUTTON_LEFT:1725/*1726* The clearlooks engine will draw a "left" button when:1727* x == w->allocation.x1728*1729* The ubuntulooks engine will draw a "left" button when:1730* [x,y,width,height]1731* intersects1732* [w->alloc.x,w->alloc.y,width,height]1733*1734* The values that are set below should ensure that a "left"1735* button is rendered for both of these (and other) engines.1736*/1737gtk2_widget->allocation.x = x;1738gtk2_widget->allocation.y = y;1739gtk2_widget->allocation.width = width;1740gtk2_widget->allocation.height = height;1741break;1742case HSCROLL_BAR_BUTTON_RIGHT:1743/*1744* The clearlooks engine will draw a "right" button when:1745* x + width == w->allocation.x + w->allocation.width1746*1747* The ubuntulooks engine will draw a "right" button when:1748* [x,y,width,height]1749* does not intersect1750* [w->alloc.x,w->alloc.y,width,height]1751* but does intersect1752* [w->alloc.x+width,w->alloc.y,width,height]1753*1754* The values that are set below should ensure that a "right"1755* button is rendered for both of these (and other) engines.1756*/1757gtk2_widget->allocation.x = x+width;1758gtk2_widget->allocation.y = 0;1759gtk2_widget->allocation.width = 0;1760gtk2_widget->allocation.height = height;1761break;1762case VSCROLL_BAR_BUTTON_UP:1763/*1764* The clearlooks engine will draw an "up" button when:1765* y == w->allocation.y1766*1767* The ubuntulooks engine will draw an "up" button when:1768* [x,y,width,height]1769* intersects1770* [w->alloc.x,w->alloc.y,width,height]1771*1772* The values that are set below should ensure that an "up"1773* button is rendered for both of these (and other) engines.1774*/1775gtk2_widget->allocation.x = x;1776gtk2_widget->allocation.y = y;1777gtk2_widget->allocation.width = width;1778gtk2_widget->allocation.height = height;1779break;1780case VSCROLL_BAR_BUTTON_DOWN:1781/*1782* The clearlooks engine will draw a "down" button when:1783* y + height == w->allocation.y + w->allocation.height1784*1785* The ubuntulooks engine will draw a "down" button when:1786* [x,y,width,height]1787* does not intersect1788* [w->alloc.x,w->alloc.y,width,height]1789* but does intersect1790* [w->alloc.x,w->alloc.y+height,width,height]1791*1792* The values that are set below should ensure that a "down"1793* button is rendered for both of these (and other) engines.1794*/1795gtk2_widget->allocation.x = x;1796gtk2_widget->allocation.y = y+height;1797gtk2_widget->allocation.width = width;1798gtk2_widget->allocation.height = 0;1799break;1800default:1801break;1802}18031804(*fp_gtk_paint_box)(gtk2_widget->style, gtk2_white_pixmap, state_type,1805shadow_type, NULL, gtk2_widget, detail, x, y, width, height);1806(*fp_gtk_paint_box)(gtk2_widget->style, gtk2_black_pixmap, state_type,1807shadow_type, NULL, gtk2_widget, detail, x, y, width, height);18081809/*1810* Reset the text direction to the default value so that we don't1811* accidentally affect other operations and widgets.1812*/1813gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);1814}18151816void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type,1817GtkShadowType shadow_type, const gchar *detail,1818gint x, gint y, gint width, gint height,1819GtkPositionType gap_side, gint gap_x, gint gap_width)1820{1821/* Clearlooks needs a real clip area to paint the gap properly */1822GdkRectangle area = { x, y, width, height };18231824gtk2_widget = gtk2_get_widget(widget_type);1825(*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_white_pixmap, state_type,1826shadow_type, &area, gtk2_widget, detail,1827x, y, width, height, gap_side, gap_x, gap_width);1828(*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_black_pixmap, state_type,1829shadow_type, &area, gtk2_widget, detail,1830x, y, width, height, gap_side, gap_x, gap_width);1831}18321833static void gtk2_paint_check(WidgetType widget_type, gint synth_state,1834const gchar *detail, gint x, gint y, gint width, gint height)1835{1836GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);1837GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);18381839gtk2_widget = gtk2_get_widget(widget_type);1840init_toggle_widget(widget_type, synth_state);18411842(*fp_gtk_paint_check)(gtk2_widget->style, gtk2_white_pixmap, state_type,1843shadow_type, NULL, gtk2_widget, detail,1844x, y, width, height);1845(*fp_gtk_paint_check)(gtk2_widget->style, gtk2_black_pixmap, state_type,1846shadow_type, NULL, gtk2_widget, detail,1847x, y, width, height);1848}18491850static void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,1851GtkShadowType shadow_type, const gchar *detail,1852gint x, gint y, gint width, gint height)1853{1854gtk2_widget = gtk2_get_widget(widget_type);1855(*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_white_pixmap, state_type,1856shadow_type, NULL, gtk2_widget, detail,1857x, y, width, height);1858(*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_black_pixmap, state_type,1859shadow_type, NULL, gtk2_widget, detail,1860x, y, width, height);1861}18621863static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,1864const gchar *detail, gint x, gint y, gint width, gint height,1865GtkExpanderStyle expander_style)1866{1867gtk2_widget = gtk2_get_widget(widget_type);1868(*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_white_pixmap,1869state_type, NULL, gtk2_widget, detail,1870x + width / 2, y + height / 2, expander_style);1871(*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_black_pixmap,1872state_type, NULL, gtk2_widget, detail,1873x + width / 2, y + height / 2, expander_style);1874}18751876static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,1877GtkShadowType shadow_type, const gchar *detail,1878gint x, gint y, gint width, gint height, GtkPositionType gap_side)1879{1880gtk2_widget = gtk2_get_widget(widget_type);1881(*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_white_pixmap,1882state_type, shadow_type, NULL, gtk2_widget, detail,1883x, y, width, height, gap_side);1884(*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_black_pixmap,1885state_type, shadow_type, NULL, gtk2_widget, detail,1886x, y, width, height, gap_side);1887}18881889static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,1890GtkShadowType shadow_type, const gchar *detail,1891gint x, gint y, gint width, gint height, gboolean has_focus)1892{1893gtk2_widget = gtk2_get_widget(widget_type);18941895if (has_focus)1896((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;1897else1898((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;18991900(*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_white_pixmap,1901state_type, shadow_type, NULL, gtk2_widget, detail,1902x, y, width, height);1903(*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_black_pixmap,1904state_type, shadow_type, NULL, gtk2_widget, detail,1905x, y, width, height);1906}19071908static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,1909const char *detail, gint x, gint y, gint width, gint height)1910{1911gtk2_widget = gtk2_get_widget(widget_type);1912(*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_white_pixmap, state_type,1913NULL, gtk2_widget, detail, x, y, width, height);1914(*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_black_pixmap, state_type,1915NULL, gtk2_widget, detail, x, y, width, height);1916}19171918static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,1919GtkShadowType shadow_type, const gchar *detail,1920gint x, gint y, gint width, gint height, GtkOrientation orientation)1921{1922gtk2_widget = gtk2_get_widget(widget_type);1923(*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_white_pixmap, state_type,1924shadow_type, NULL, gtk2_widget, detail,1925x, y, width, height, orientation);1926(*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_black_pixmap, state_type,1927shadow_type, NULL, gtk2_widget, detail,1928x, y, width, height, orientation);1929}19301931static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,1932const gchar *detail, gint x, gint y, gint width, gint height)1933{1934gtk2_widget = gtk2_get_widget(widget_type);1935(*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_white_pixmap, state_type,1936NULL, gtk2_widget, detail, x, x + width, y);1937(*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_black_pixmap, state_type,1938NULL, gtk2_widget, detail, x, x + width, y);1939}19401941static void gtk2_paint_option(WidgetType widget_type, gint synth_state,1942const gchar *detail, gint x, gint y, gint width, gint height)1943{1944GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);1945GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);19461947gtk2_widget = gtk2_get_widget(widget_type);1948init_toggle_widget(widget_type, synth_state);19491950(*fp_gtk_paint_option)(gtk2_widget->style, gtk2_white_pixmap, state_type,1951shadow_type, NULL, gtk2_widget, detail,1952x, y, width, height);1953(*fp_gtk_paint_option)(gtk2_widget->style, gtk2_black_pixmap, state_type,1954shadow_type, NULL, gtk2_widget, detail,1955x, y, width, height);1956}19571958static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,1959GtkShadowType shadow_type, const gchar *detail,1960gint x, gint y, gint width, gint height,1961gint synth_state, GtkTextDirection dir)1962{1963gtk2_widget = gtk2_get_widget(widget_type);19641965/*1966* The clearlooks engine sometimes looks at the widget's state field1967* instead of just the state_type variable that we pass in, so to account1968* for those cases we set the widget's state field accordingly. The1969* flags field is similarly important for things like focus state.1970*/1971gtk2_widget->state = state_type;19721973/*1974* Some engines (e.g. clearlooks) will paint the shadow of certain1975* widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the1976* the text direction.1977*/1978gtk2_set_direction(gtk2_widget, dir);19791980switch (widget_type) {1981case COMBO_BOX_TEXT_FIELD:1982case FORMATTED_TEXT_FIELD:1983case PASSWORD_FIELD:1984case SPINNER_TEXT_FIELD:1985case TEXT_FIELD:1986if (synth_state & FOCUSED) {1987((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;1988} else {1989((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;1990}1991break;1992default:1993break;1994}19951996(*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_white_pixmap, state_type,1997shadow_type, NULL, gtk2_widget, detail, x, y, width, height);1998(*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_black_pixmap, state_type,1999shadow_type, NULL, gtk2_widget, detail, x, y, width, height);20002001/*2002* Reset the text direction to the default value so that we don't2003* accidentally affect other operations and widgets.2004*/2005gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);2006}20072008static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,2009GtkShadowType shadow_type, const gchar *detail,2010gint x, gint y, gint width, gint height, GtkOrientation orientation,2011gboolean has_focus)2012{2013gtk2_widget = gtk2_get_widget(widget_type);2014(*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type,2015shadow_type, NULL, gtk2_widget, detail,2016x, y, width, height, orientation);2017(*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_black_pixmap, state_type,2018shadow_type, NULL, gtk2_widget, detail,2019x, y, width, height, orientation);2020}20212022static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,2023const gchar *detail, gint x, gint y, gint width, gint height)2024{2025gtk2_widget = gtk2_get_widget(widget_type);2026(*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_white_pixmap, state_type,2027NULL, gtk2_widget, detail, y, y + height, x);2028(*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_black_pixmap, state_type,2029NULL, gtk2_widget, detail, y, y + height, x);2030}20312032static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,2033gint x, gint y, gint width, gint height)2034{2035gtk2_widget = gtk2_get_widget(widget_type);2036(*fp_gtk_style_apply_default_background)(gtk2_widget->style,2037gtk2_white_pixmap, TRUE, state_type, NULL, x, y, width, height);2038(*fp_gtk_style_apply_default_background)(gtk2_widget->style,2039gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height);2040}20412042static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,2043GtkIconSize size, GtkTextDirection direction, const char *detail)2044{2045init_containers();2046gtk2_widget = gtk2_get_widget((widget_type < 0) ? IMAGE : widget_type);2047gtk2_widget->state = GTK_STATE_NORMAL;2048(*fp_gtk_widget_set_direction)(gtk2_widget, direction);2049return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail);2050}20512052static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf,2053jmethodID icon_upcall_method, jobject this) {2054if (!pixbuf) {2055return JNI_FALSE;2056}2057guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);2058if (pixbuf_data) {2059int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);2060int width = (*fp_gdk_pixbuf_get_width)(pixbuf);2061int height = (*fp_gdk_pixbuf_get_height)(pixbuf);2062int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);2063int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);2064gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);20652066jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));2067JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);20682069(*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),2070(jbyte *)pixbuf_data);2071(*fp_g_object_unref)(pixbuf);20722073/* Call the callback method to create the image on the Java side. */2074(*env)->CallVoidMethod(env, this, icon_upcall_method, data,2075width, height, row_stride, bps, channels, alpha);2076return JNI_TRUE;2077}2078return JNI_FALSE;2079}20802081static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename,2082GError **error, jmethodID icon_upcall_method, jobject this) {2083GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error);2084return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);2085}20862087static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type,2088const gchar *stock_id, GtkIconSize size,2089GtkTextDirection direction, const char *detail,2090jmethodID icon_upcall_method, jobject this) {2091GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size,2092direction, detail);2093return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);2094}20952096/*************************************************/2097static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type)2098{2099init_containers();21002101gtk2_widget = gtk2_get_widget(widget_type);2102GtkStyle* style = gtk2_widget->style;2103return style->xthickness;2104}21052106static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type)2107{2108init_containers();21092110gtk2_widget = gtk2_get_widget(widget_type);2111GtkStyle* style = gtk2_widget->style;2112return style->ythickness;2113}21142115/*************************************************/2116static guint8 recode_color(guint16 channel)2117{2118return (guint8)(channel>>8);2119}21202121static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,2122GtkStateType state_type, ColorType color_type)2123{2124gint result = 0;2125GdkColor *color = NULL;21262127init_containers();21282129gtk2_widget = gtk2_get_widget(widget_type);2130GtkStyle* style = gtk2_widget->style;21312132switch (color_type)2133{2134case FOREGROUND:2135color = &(style->fg[state_type]);2136break;2137case BACKGROUND:2138color = &(style->bg[state_type]);2139break;2140case TEXT_FOREGROUND:2141color = &(style->text[state_type]);2142break;2143case TEXT_BACKGROUND:2144color = &(style->base[state_type]);2145break;2146case LIGHT:2147color = &(style->light[state_type]);2148break;2149case DARK:2150color = &(style->dark[state_type]);2151break;2152case MID:2153color = &(style->mid[state_type]);2154break;2155case FOCUS:2156case BLACK:2157color = &(style->black);2158break;2159case WHITE:2160color = &(style->white);2161break;2162}21632164if (color)2165result = recode_color(color->red) << 16 |2166recode_color(color->green) << 8 |2167recode_color(color->blue);21682169return result;2170}21712172/*************************************************/2173static jobject create_Boolean(JNIEnv *env, jboolean boolean_value);2174static jobject create_Integer(JNIEnv *env, jint int_value);2175static jobject create_Long(JNIEnv *env, jlong long_value);2176static jobject create_Float(JNIEnv *env, jfloat float_value);2177static jobject create_Double(JNIEnv *env, jdouble double_value);2178static jobject create_Character(JNIEnv *env, jchar char_value);2179static jobject create_Insets(JNIEnv *env, GtkBorder *border);21802181static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type,2182const char* key)2183{2184init_containers();21852186gtk2_widget = gtk2_get_widget(widget_type);21872188GValue value;2189value.g_type = 0;21902191GParamSpec* param = (*fp_gtk_widget_class_find_style_property)(2192((GTypeInstance*)gtk2_widget)->g_class, key);2193if( param )2194{2195(*fp_g_value_init)( &value, param->value_type );2196(*fp_gtk_widget_style_get_property)(gtk2_widget, key, &value);21972198if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN ))2199{2200gboolean val = (*fp_g_value_get_boolean)(&value);2201return create_Boolean(env, (jboolean)val);2202}2203else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR ))2204{2205gchar val = (*fp_g_value_get_char)(&value);2206return create_Character(env, (jchar)val);2207}2208else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR ))2209{2210guchar val = (*fp_g_value_get_uchar)(&value);2211return create_Character(env, (jchar)val);2212}2213else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT ))2214{2215gint val = (*fp_g_value_get_int)(&value);2216return create_Integer(env, (jint)val);2217}2218else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT ))2219{2220guint val = (*fp_g_value_get_uint)(&value);2221return create_Integer(env, (jint)val);2222}2223else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_LONG ))2224{2225glong val = (*fp_g_value_get_long)(&value);2226return create_Long(env, (jlong)val);2227}2228else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG ))2229{2230gulong val = (*fp_g_value_get_ulong)(&value);2231return create_Long(env, (jlong)val);2232}2233else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 ))2234{2235gint64 val = (*fp_g_value_get_int64)(&value);2236return create_Long(env, (jlong)val);2237}2238else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 ))2239{2240guint64 val = (*fp_g_value_get_uint64)(&value);2241return create_Long(env, (jlong)val);2242}2243else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT ))2244{2245gfloat val = (*fp_g_value_get_float)(&value);2246return create_Float(env, (jfloat)val);2247}2248else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE ))2249{2250gdouble val = (*fp_g_value_get_double)(&value);2251return create_Double(env, (jdouble)val);2252}2253else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM ))2254{2255gint val = (*fp_g_value_get_enum)(&value);2256return create_Integer(env, (jint)val);2257}2258else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS ))2259{2260guint val = (*fp_g_value_get_flags)(&value);2261return create_Integer(env, (jint)val);2262}2263else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_STRING ))2264{2265const gchar* val = (*fp_g_value_get_string)(&value);22662267/* We suppose that all values come in C locale and2268* utf-8 representation of a string is the same as2269* the string itself. If this isn't so we should2270* use g_convert.2271*/2272return (*env)->NewStringUTF(env, val);2273}2274else if( (*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER ))2275{2276GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value);2277return border ? create_Insets(env, border) : NULL;2278}22792280/* TODO: Other types are not supported yet.*/2281/* else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM ))2282{2283GParamSpec* val = (*fp_g_value_get_param)(&value);2284printf( "Param: %p\n", val );2285}2286else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED ))2287{2288gpointer* val = (*fp_g_value_get_boxed)(&value);2289printf( "Boxed: %p\n", val );2290}2291else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER ))2292{2293gpointer* val = (*fp_g_value_get_pointer)(&value);2294printf( "Pointer: %p\n", val );2295}2296else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT ))2297{2298GObject* val = (GObject*)(*fp_g_value_get_object)(&value);2299printf( "Object: %p\n", val );2300}*/2301}23022303return NULL;2304}23052306static void gtk2_set_range_value(WidgetType widget_type, jdouble value,2307jdouble min, jdouble max, jdouble visible)2308{2309GtkAdjustment *adj;23102311gtk2_widget = gtk2_get_widget(widget_type);23122313adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk2_widget);2314adj->value = (gdouble)value;2315adj->lower = (gdouble)min;2316adj->upper = (gdouble)max;2317adj->page_size = (gdouble)visible;2318}23192320/*************************************************/2321static jobject create_Object(JNIEnv *env, jmethodID *cid,2322const char* class_name,2323const char* signature,2324jvalue* value)2325{2326jclass class;2327jobject result;23282329class = (*env)->FindClass(env, class_name);2330if( class == NULL )2331return NULL; /* can't find/load the class, exception thrown */23322333if( *cid == NULL)2334{2335*cid = (*env)->GetMethodID(env, class, "<init>", signature);2336if( *cid == NULL )2337{2338(*env)->DeleteLocalRef(env, class);2339return NULL; /* can't find/get the method, exception thrown */2340}2341}23422343result = (*env)->NewObjectA(env, class, *cid, value);23442345(*env)->DeleteLocalRef(env, class);2346return result;2347}23482349jobject create_Boolean(JNIEnv *env, jboolean boolean_value)2350{2351static jmethodID cid = NULL;2352jvalue value;23532354value.z = boolean_value;23552356return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value);2357}23582359jobject create_Integer(JNIEnv *env, jint int_value)2360{2361static jmethodID cid = NULL;2362jvalue value;23632364value.i = int_value;23652366return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value);2367}23682369jobject create_Long(JNIEnv *env, jlong long_value)2370{2371static jmethodID cid = NULL;2372jvalue value;23732374value.j = long_value;23752376return create_Object(env, &cid, "java/lang/Long", "(J)V", &value);2377}23782379jobject create_Float(JNIEnv *env, jfloat float_value)2380{2381static jmethodID cid = NULL;2382jvalue value;23832384value.f = float_value;23852386return create_Object(env, &cid, "java/lang/Float", "(F)V", &value);2387}23882389jobject create_Double(JNIEnv *env, jdouble double_value)2390{2391static jmethodID cid = NULL;2392jvalue value;23932394value.d = double_value;23952396return create_Object(env, &cid, "java/lang/Double", "(D)V", &value);2397}23982399jobject create_Character(JNIEnv *env, jchar char_value)2400{2401static jmethodID cid = NULL;2402jvalue value;24032404value.c = char_value;24052406return create_Object(env, &cid, "java/lang/Character", "(C)V", &value);2407}240824092410jobject create_Insets(JNIEnv *env, GtkBorder *border)2411{2412static jmethodID cid = NULL;2413jvalue values[4];24142415values[0].i = border->top;2416values[1].i = border->left;2417values[2].i = border->bottom;2418values[3].i = border->right;24192420return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values);2421}24222423/*********************************************/2424static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type)2425{2426init_containers();24272428gtk2_widget = gtk2_get_widget(widget_type);2429jstring result = NULL;2430GtkStyle* style = gtk2_widget->style;24312432if (style && style->font_desc)2433{2434gchar* val = (*fp_pango_font_description_to_string)(style->font_desc);2435result = (*env)->NewStringUTF(env, val);2436(*fp_g_free)( val );2437}24382439return result;2440}24412442/***********************************************/2443static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key)2444{2445jobject result = NULL;2446gchar* strval = NULL;24472448(*fp_g_object_get)(settings, key, &strval, NULL);2449result = (*env)->NewStringUTF(env, strval);2450(*fp_g_free)(strval);24512452return result;2453}24542455static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)2456{2457gint intval = 0;2458(*fp_g_object_get)(settings, key, &intval, NULL);2459return create_Integer(env, intval);2460}24612462static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key)2463{2464gint intval = 0;2465(*fp_g_object_get)(settings, key, &intval, NULL);2466return create_Boolean(env, intval);2467}24682469static jobject gtk2_get_setting(JNIEnv *env, Setting property)2470{2471GtkSettings* settings = (*fp_gtk_settings_get_default)();24722473switch (property)2474{2475case GTK_FONT_NAME:2476return get_string_property(env, settings, "gtk-font-name");2477case GTK_ICON_SIZES:2478return get_string_property(env, settings, "gtk-icon-sizes");2479case GTK_CURSOR_BLINK:2480return get_boolean_property(env, settings, "gtk-cursor-blink");2481case GTK_CURSOR_BLINK_TIME:2482return get_integer_property(env, settings, "gtk-cursor-blink-time");2483}24842485return NULL;2486}24872488static GdkWindow* gtk2_get_window(void *widget) {2489return ((GtkWidget*)widget)->window;2490}24912492void gtk2_init(GtkApi* gtk) {2493gtk->version = GTK_2;24942495gtk->show_uri_load = >k2_show_uri_load;2496gtk->unload = >k2_unload;2497gtk->flush_event_loop = &flush_gtk_event_loop;2498gtk->gtk_check_version = fp_gtk_check_version;2499gtk->get_setting = >k2_get_setting;25002501gtk->paint_arrow = >k2_paint_arrow;2502gtk->paint_box = >k2_paint_box;2503gtk->paint_box_gap = >k2_paint_box_gap;2504gtk->paint_expander = >k2_paint_expander;2505gtk->paint_extension = >k2_paint_extension;2506gtk->paint_flat_box = >k2_paint_flat_box;2507gtk->paint_focus = >k2_paint_focus;2508gtk->paint_handle = >k2_paint_handle;2509gtk->paint_hline = >k2_paint_hline;2510gtk->paint_vline = >k2_paint_vline;2511gtk->paint_option = >k2_paint_option;2512gtk->paint_shadow = >k2_paint_shadow;2513gtk->paint_slider = >k2_paint_slider;2514gtk->paint_background = >k_paint_background;2515gtk->paint_check = >k2_paint_check;2516gtk->set_range_value = >k2_set_range_value;25172518gtk->init_painting = >k2_init_painting;2519gtk->copy_image = >k2_copy_image;25202521gtk->get_xthickness = >k2_get_xthickness;2522gtk->get_ythickness = >k2_get_ythickness;2523gtk->get_color_for_state = >k2_get_color_for_state;2524gtk->get_class_value = >k2_get_class_value;25252526gtk->get_pango_font_name = >k2_get_pango_font_name;2527gtk->get_icon_data = >k2_get_icon_data;2528gtk->get_file_icon_data = >k2_get_file_icon_data;2529gtk->gdk_threads_enter = fp_gdk_threads_enter;2530gtk->gdk_threads_leave = fp_gdk_threads_leave;2531gtk->gtk_show_uri = fp_gtk_show_uri;2532gtk->g_free = fp_g_free;25332534gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename;2535gtk->gtk_widget_hide = fp_gtk_widget_hide;2536gtk->gtk_main_quit = fp_gtk_main_quit;2537gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new;2538gtk->gtk_file_chooser_set_current_folder =2539fp_gtk_file_chooser_set_current_folder;2540gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename;2541gtk->gtk_file_chooser_set_current_name =2542fp_gtk_file_chooser_set_current_name;2543gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom;2544gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter;2545gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type;2546gtk->gtk_file_filter_new = fp_gtk_file_filter_new;2547gtk->gtk_file_chooser_set_do_overwrite_confirmation =2548fp_gtk_file_chooser_set_do_overwrite_confirmation;2549gtk->gtk_file_chooser_set_select_multiple =2550fp_gtk_file_chooser_set_select_multiple;2551gtk->gtk_file_chooser_get_current_folder =2552fp_gtk_file_chooser_get_current_folder;2553gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames;2554gtk->gtk_g_slist_length = fp_gtk_g_slist_length;2555gtk->g_signal_connect_data = fp_g_signal_connect_data;2556gtk->gtk_widget_show = fp_gtk_widget_show;2557gtk->gtk_main = fp_gtk_main;2558gtk->gtk_main_level = fp_gtk_main_level;2559gtk->g_path_get_dirname = fp_g_path_get_dirname;2560gtk->gtk_widget_destroy = fp_gtk_widget_destroy;2561gtk->gtk_window_present = fp_gtk_window_present;2562gtk->gtk_window_move = fp_gtk_window_move;2563gtk->gtk_window_resize = fp_gtk_window_resize;2564gtk->get_window = >k2_get_window;25652566gtk->g_object_unref = fp_g_object_unref;2567gtk->g_list_append = fp_g_list_append;2568gtk->g_list_free = fp_g_list_free;2569gtk->g_list_free_full = fp_g_list_free_full;2570}257125722573