Path: blob/master/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c
41155 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*/2425#ifdef HEADLESS26#error This file should not be included in headless library27#endif2829#include <dlfcn.h>30#include <setjmp.h>31#include <X11/Xlib.h>32#include <limits.h>33#include <stdio.h>34#include <string.h>35#include "gtk2_interface.h"36#include "java_awt_Transparency.h"37#include "jvm_md.h"38#include "sizecalc.h"39#include <jni_util.h>40#include "awt.h"4142#define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)())4344#define G_TYPE_FUNDAMENTAL_SHIFT (2)45#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))4647#define CONV_BUFFER_SIZE 1284849#define NO_SYMBOL_EXCEPTION 15051static void *gtk2_libhandle = NULL;52static void *gthread_libhandle = NULL;5354static jmp_buf j;5556/* Widgets */57static GtkWidget *gtk2_widget = NULL;58static GtkWidget *gtk2_window = NULL;59static GtkFixed *gtk2_fixed = NULL;6061/* Paint system */62static GdkPixmap *gtk2_white_pixmap = NULL;63static GdkPixmap *gtk2_black_pixmap = NULL;64static GdkPixbuf *gtk2_white_pixbuf = NULL;65static GdkPixbuf *gtk2_black_pixbuf = NULL;66static int gtk2_pixbuf_width = 0;67static int gtk2_pixbuf_height = 0;6869/* Static buffer for conversion from java.lang.String to UTF-8 */70static char convertionBuffer[CONV_BUFFER_SIZE];7172static gboolean new_combo = TRUE;73const char ENV_PREFIX[] = "GTK_MODULES=";747576static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE];7778/*************************79* Glib function pointers80*************************/8182static gboolean (*fp_g_main_context_iteration)(GMainContext *context,83gboolean may_block);8485static GValue* (*fp_g_value_init)(GValue *value, GType g_type);86static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type);87static gboolean (*fp_g_value_get_boolean)(const GValue *value);88static gchar (*fp_g_value_get_char)(const GValue *value);89static guchar (*fp_g_value_get_uchar)(const GValue *value);90static gint (*fp_g_value_get_int)(const GValue *value);91static guint (*fp_g_value_get_uint)(const GValue *value);92static glong (*fp_g_value_get_long)(const GValue *value);93static gulong (*fp_g_value_get_ulong)(const GValue *value);94static gint64 (*fp_g_value_get_int64)(const GValue *value);95static guint64 (*fp_g_value_get_uint64)(const GValue *value);96static gfloat (*fp_g_value_get_float)(const GValue *value);97static gdouble (*fp_g_value_get_double)(const GValue *value);98static const gchar* (*fp_g_value_get_string)(const GValue *value);99static gint (*fp_g_value_get_enum)(const GValue *value);100static guint (*fp_g_value_get_flags)(const GValue *value);101static GParamSpec* (*fp_g_value_get_param)(const GValue *value);102static gpointer* (*fp_g_value_get_boxed)(const GValue *value);103static gpointer* (*fp_g_value_get_pointer)(const GValue *value);104static GObject* (*fp_g_value_get_object)(const GValue *value);105static GParamSpec* (*fp_g_param_spec_int)(const gchar *name,106const gchar *nick, const gchar *blurb,107gint minimum, gint maximum, gint default_value,108GParamFlags flags);109static void (*fp_g_object_get)(gpointer object,110const gchar* fpn, ...);111static void (*fp_g_object_set)(gpointer object,112const gchar *first_property_name,113...);114/************************115* GDK function pointers116************************/117static GdkPixmap *(*fp_gdk_pixmap_new)(GdkDrawable *drawable,118gint width, gint height, gint depth);119static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*);120static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32);121static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean,122gint, gint, gint, gint);123static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace,124gboolean has_alpha, int bits_per_sample, int width, int height);125static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable,126gint* width, gint* height);127128/************************129* Gtk function pointers130************************/131static gboolean (*fp_gtk_init_check)(int* argc, char** argv);132133/* Painting */134static void (*fp_gtk_paint_hline)(GtkStyle* style, GdkWindow* window,135GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,136const gchar* detail, gint x1, gint x2, gint y);137static void (*fp_gtk_paint_vline)(GtkStyle* style, GdkWindow* window,138GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,139const gchar* detail, gint y1, gint y2, gint x);140static void (*fp_gtk_paint_shadow)(GtkStyle* style, GdkWindow* window,141GtkStateType state_type, GtkShadowType shadow_type,142GdkRectangle* area, GtkWidget* widget, const gchar* detail,143gint x, gint y, gint width, gint height);144static void (*fp_gtk_paint_arrow)(GtkStyle* style, GdkWindow* window,145GtkStateType state_type, GtkShadowType shadow_type,146GdkRectangle* area, GtkWidget* widget, const gchar* detail,147GtkArrowType arrow_type, gboolean fill, gint x, gint y,148gint width, gint height);149static void (*fp_gtk_paint_diamond)(GtkStyle* style, GdkWindow* window,150GtkStateType state_type, GtkShadowType shadow_type,151GdkRectangle* area, GtkWidget* widget, const gchar* detail,152gint x, gint y, gint width, gint height);153static void (*fp_gtk_paint_box)(GtkStyle* style, GdkWindow* window,154GtkStateType state_type, GtkShadowType shadow_type,155GdkRectangle* area, GtkWidget* widget, const gchar* detail,156gint x, gint y, gint width, gint height);157static void (*fp_gtk_paint_flat_box)(GtkStyle* style, GdkWindow* window,158GtkStateType state_type, GtkShadowType shadow_type,159GdkRectangle* area, GtkWidget* widget, const gchar* detail,160gint x, gint y, gint width, gint height);161static void (*fp_gtk_paint_check)(GtkStyle* style, GdkWindow* window,162GtkStateType state_type, GtkShadowType shadow_type,163GdkRectangle* area, GtkWidget* widget, const gchar* detail,164gint x, gint y, gint width, gint height);165static void (*fp_gtk_paint_option)(GtkStyle* style, GdkWindow* window,166GtkStateType state_type, GtkShadowType shadow_type,167GdkRectangle* area, GtkWidget* widget, const gchar* detail,168gint x, gint y, gint width, gint height);169static void (*fp_gtk_paint_box_gap)(GtkStyle* style, GdkWindow* window,170GtkStateType state_type, GtkShadowType shadow_type,171GdkRectangle* area, GtkWidget* widget, const gchar* detail,172gint x, gint y, gint width, gint height,173GtkPositionType gap_side, gint gap_x, gint gap_width);174static void (*fp_gtk_paint_extension)(GtkStyle* style, GdkWindow* window,175GtkStateType state_type, GtkShadowType shadow_type,176GdkRectangle* area, GtkWidget* widget, const gchar* detail,177gint x, gint y, gint width, gint height, GtkPositionType gap_side);178static void (*fp_gtk_paint_focus)(GtkStyle* style, GdkWindow* window,179GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,180const gchar* detail, gint x, gint y, gint width, gint height);181static void (*fp_gtk_paint_slider)(GtkStyle* style, GdkWindow* window,182GtkStateType state_type, GtkShadowType shadow_type,183GdkRectangle* area, GtkWidget* widget, const gchar* detail,184gint x, gint y, gint width, gint height, GtkOrientation orientation);185static void (*fp_gtk_paint_handle)(GtkStyle* style, GdkWindow* window,186GtkStateType state_type, GtkShadowType shadow_type,187GdkRectangle* area, GtkWidget* widget, const gchar* detail,188gint x, gint y, gint width, gint height, GtkOrientation orientation);189static void (*fp_gtk_paint_expander)(GtkStyle* style, GdkWindow* window,190GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,191const gchar* detail, gint x, gint y, GtkExpanderStyle expander_style);192static void (*fp_gtk_style_apply_default_background)(GtkStyle* style,193GdkWindow* window, gboolean set_bg, GtkStateType state_type,194GdkRectangle* area, gint x, gint y, gint width, gint height);195196/* Widget creation */197static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type,198GtkShadowType shadow_type);199static GtkWidget* (*fp_gtk_button_new)();200static GtkWidget* (*fp_gtk_check_button_new)();201static GtkWidget* (*fp_gtk_check_menu_item_new)();202static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title);203static GtkWidget* (*fp_gtk_combo_box_new)();204static GtkWidget* (*fp_gtk_combo_box_entry_new)();205static GtkWidget* (*fp_gtk_entry_new)();206static GtkWidget* (*fp_gtk_fixed_new)();207static GtkWidget* (*fp_gtk_handle_box_new)();208static GtkWidget* (*fp_gtk_hpaned_new)();209static GtkWidget* (*fp_gtk_vpaned_new)();210static GtkWidget* (*fp_gtk_hscale_new)(GtkAdjustment* adjustment);211static GtkWidget* (*fp_gtk_vscale_new)(GtkAdjustment* adjustment);212static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment);213static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment);214static GtkWidget* (*fp_gtk_hseparator_new)();215static GtkWidget* (*fp_gtk_vseparator_new)();216static GtkWidget* (*fp_gtk_image_new)();217static GtkWidget* (*fp_gtk_label_new)(const gchar* str);218static GtkWidget* (*fp_gtk_menu_new)();219static GtkWidget* (*fp_gtk_menu_bar_new)();220static GtkWidget* (*fp_gtk_menu_item_new)();221static GtkWidget* (*fp_gtk_notebook_new)();222static GtkWidget* (*fp_gtk_progress_bar_new)();223static GtkWidget* (*fp_gtk_progress_bar_set_orientation)(224GtkProgressBar *pbar,225GtkProgressBarOrientation orientation);226static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group);227static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group);228static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment,229GtkAdjustment *vadjustment);230static GtkWidget* (*fp_gtk_separator_menu_item_new)();231static GtkWidget* (*fp_gtk_separator_tool_item_new)();232static GtkWidget* (*fp_gtk_text_view_new)();233static GtkWidget* (*fp_gtk_toggle_button_new)();234static GtkWidget* (*fp_gtk_toolbar_new)();235static GtkWidget* (*fp_gtk_tree_view_new)();236static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment,237GtkAdjustment *vadjustment);238static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type);239static GtkWidget* (*fp_gtk_dialog_new)();240static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment,241gdouble climb_rate, guint digits);242static GtkWidget* (*fp_gtk_frame_new)(const gchar *label);243244/* Other widget operations */245static GtkObject* (*fp_gtk_adjustment_new)(gdouble value,246gdouble lower, gdouble upper, gdouble step_increment,247gdouble page_increment, gdouble page_size);248static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget);249static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell,250GtkWidget *child);251static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item,252GtkWidget *submenu);253static void (*fp_gtk_widget_realize)(GtkWidget *widget);254static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget,255const gchar *stock_id, GtkIconSize size, const gchar *detail);256static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name);257static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent);258static void (*fp_gtk_widget_set_direction)(GtkWidget *widget,259GtkTextDirection direction);260static void (*fp_gtk_widget_style_get)(GtkWidget *widget,261const gchar *first_property_name, ...);262static void (*fp_gtk_widget_class_install_style_property)(263GtkWidgetClass* class, GParamSpec *pspec);264static GParamSpec* (*fp_gtk_widget_class_find_style_property)(265GtkWidgetClass* class, const gchar* property_name);266static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget,267const gchar* property_name, GValue* value);268static char* (*fp_pango_font_description_to_string)(269const PangoFontDescription* fd);270static GtkSettings* (*fp_gtk_settings_get_default)();271static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget);272static GType (*fp_gtk_border_get_type)();273static void (*fp_gtk_arrow_set)(GtkWidget* arrow,274GtkArrowType arrow_type,275GtkShadowType shadow_type);276static void (*fp_gtk_widget_size_request)(GtkWidget *widget,277GtkRequisition *requisition);278static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range);279280/* Method bodies */281282static void throw_exception(JNIEnv *env, const char* name, const char* message)283{284jclass class = (*env)->FindClass(env, name);285286if (class != NULL)287(*env)->ThrowNew(env, class, message);288289(*env)->DeleteLocalRef(env, class);290}291292/* This is a workaround for the bug:293* http://sourceware.org/bugzilla/show_bug.cgi?id=1814294* (dlsym/dlopen clears dlerror state)295* This bug is specific to Linux, but there is no harm in296* applying this workaround on Solaris as well.297*/298static void* dl_symbol(const char* name)299{300void* result = dlsym(gtk2_libhandle, name);301if (!result)302longjmp(j, NO_SYMBOL_EXCEPTION);303304return result;305}306307static void* dl_symbol_gthread(const char* name)308{309void* result = dlsym(gthread_libhandle, name);310if (!result)311longjmp(j, NO_SYMBOL_EXCEPTION);312313return result;314}315316gboolean gtk2_check(const char* lib_name, gboolean load)317{318if (gtk2_libhandle != NULL) {319/* We've already successfully opened the GTK libs, so return true. */320return TRUE;321} else {322void *lib = NULL;323324#ifdef RTLD_NOLOAD325/* Just check if gtk libs are already in the process space */326lib = dlopen(lib_name, RTLD_LAZY | RTLD_NOLOAD);327if (!load || lib != NULL) {328return lib != NULL;329}330#else331#ifdef _AIX332/* On AIX we could implement this with the help of loadquery(L_GETINFO, ..) */333/* (see reload_table() in hotspot/src/os/aix/vm/loadlib_aix.cpp) but it is */334/* probably not worth it because most AIX servers don't have GTK libs anyway */335#endif336#endif337338lib = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);339if (lib == NULL) {340return FALSE;341}342343fp_gtk_check_version = dlsym(lib, "gtk_check_version");344/* Check for GTK 2.2+ */345if (!fp_gtk_check_version(2, 2, 0)) {346return TRUE;347}348349// 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065350// dlclose(lib);351352return FALSE;353}354}355356#define ADD_SUPPORTED_ACTION(actionStr) \357do { \358jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, "Ljava/awt/Desktop$Action;"); \359if (!(*env)->ExceptionCheck(env)) { \360jobject action = (*env)->GetStaticObjectField(env, cls_action, fld_action); \361(*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, action); \362} else { \363(*env)->ExceptionClear(env); \364} \365} while(0);366367368static void update_supported_actions(JNIEnv *env) {369GVfs * (*fp_g_vfs_get_default) (void);370const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);371const gchar * const * schemes = NULL;372373jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action");374CHECK_NULL(cls_action);375jclass cls_xDesktopPeer = (*env)->FindClass(env, "sun/awt/X11/XDesktopPeer");376CHECK_NULL(cls_xDesktopPeer);377jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, cls_xDesktopPeer, "supportedActions", "Ljava/util/List;");378CHECK_NULL(fld_supportedActions);379jobject supportedActions = (*env)->GetStaticObjectField(env, cls_xDesktopPeer, fld_supportedActions);380381jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList");382CHECK_NULL(cls_arrayList);383jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", "(Ljava/lang/Object;)Z");384CHECK_NULL(mid_arrayListAdd);385jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, "clear", "()V");386CHECK_NULL(mid_arrayListClear);387388(*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear);389390ADD_SUPPORTED_ACTION("OPEN");391392/**393* gtk_show_uri() documentation says:394*395* > you need to install gvfs to get support for uri schemes such as http://396* > or ftp://, as only local files are handled by GIO itself.397*398* So OPEN action was safely added here.399* However, it looks like Solaris 11 have gvfs support only for 32-bit400* applications only by default.401*/402403fp_g_vfs_get_default = dl_symbol("g_vfs_get_default");404fp_g_vfs_get_supported_uri_schemes = dl_symbol("g_vfs_get_supported_uri_schemes");405dlerror();406407if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) {408GVfs * vfs = fp_g_vfs_get_default();409schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL;410if (schemes) {411int i = 0;412while (schemes[i]) {413if (strcmp(schemes[i], "http") == 0) {414ADD_SUPPORTED_ACTION("BROWSE");415ADD_SUPPORTED_ACTION("MAIL");416break;417}418i++;419}420}421} else {422#ifdef DEBUG423fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n");424#endif /* DEBUG */425}426427}428/**429* Functions for awt_Desktop.c430*/431static gboolean gtk2_show_uri_load(JNIEnv *env) {432gboolean success = FALSE;433dlerror();434const char *gtk_version = fp_gtk_check_version(2, 14, 0);435if (gtk_version != NULL) {436// The gtk_show_uri is available from GTK+ 2.14437#ifdef DEBUG438fprintf (stderr, "The version of GTK is %s. "439"The gtk_show_uri function is supported "440"since GTK+ 2.14.\n", gtk_version);441#endif /* DEBUG */442} else {443// Loading symbols only if the GTK version is 2.14 and higher444fp_gtk_show_uri = dl_symbol("gtk_show_uri");445const char *dlsym_error = dlerror();446if (dlsym_error) {447#ifdef DEBUG448fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error);449#endif /* DEBUG */450} else if (fp_gtk_show_uri == NULL) {451#ifdef DEBUG452fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");453#endif /* DEBUG */454} else {455gtk->gtk_show_uri = fp_gtk_show_uri;456update_supported_actions(env);457success = TRUE;458}459}460return success;461}462463/**464* Functions for sun_awt_X11_GtkFileDialogPeer.c465*/466static void gtk2_file_chooser_load()467{468fp_gtk_file_chooser_get_filename = dl_symbol(469"gtk_file_chooser_get_filename");470fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new");471fp_gtk_file_chooser_set_current_folder = dl_symbol(472"gtk_file_chooser_set_current_folder");473fp_gtk_file_chooser_set_filename = dl_symbol(474"gtk_file_chooser_set_filename");475fp_gtk_file_chooser_set_current_name = dl_symbol(476"gtk_file_chooser_set_current_name");477fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom");478fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");479fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");480fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");481if (fp_gtk_check_version(2, 8, 0) == NULL) {482fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(483"gtk_file_chooser_set_do_overwrite_confirmation");484}485fp_gtk_file_chooser_set_select_multiple = dl_symbol(486"gtk_file_chooser_set_select_multiple");487fp_gtk_file_chooser_get_current_folder = dl_symbol(488"gtk_file_chooser_get_current_folder");489fp_gtk_file_chooser_get_filenames = dl_symbol(490"gtk_file_chooser_get_filenames");491fp_gtk_g_slist_length = dl_symbol("g_slist_length");492fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid");493}494495GtkApi* gtk2_load(JNIEnv *env, const char* lib_name)496{497gboolean result;498int i;499int (*handler)();500int (*io_handler)();501char *gtk_modules_env;502503gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);504if (gtk2_libhandle == NULL) {505return FALSE;506}507508gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);509if (gthread_libhandle == NULL) {510gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL);511if (gthread_libhandle == NULL)512return FALSE;513}514515if (setjmp(j) == 0)516{517fp_gtk_check_version = dl_symbol("gtk_check_version");518/* Check for GTK 2.2+ */519if (fp_gtk_check_version(2, 2, 0)) {520longjmp(j, NO_SYMBOL_EXCEPTION);521}522523/* GLib */524fp_glib_check_version = dlsym(gtk2_libhandle, "glib_check_version");525if (!fp_glib_check_version) {526dlerror();527}528fp_g_free = dl_symbol("g_free");529fp_g_object_unref = dl_symbol("g_object_unref");530531fp_g_main_context_iteration =532dl_symbol("g_main_context_iteration");533534fp_g_value_init = dl_symbol("g_value_init");535fp_g_type_is_a = dl_symbol("g_type_is_a");536537fp_g_value_get_boolean = dl_symbol("g_value_get_boolean");538fp_g_value_get_char = dl_symbol("g_value_get_char");539fp_g_value_get_uchar = dl_symbol("g_value_get_uchar");540fp_g_value_get_int = dl_symbol("g_value_get_int");541fp_g_value_get_uint = dl_symbol("g_value_get_uint");542fp_g_value_get_long = dl_symbol("g_value_get_long");543fp_g_value_get_ulong = dl_symbol("g_value_get_ulong");544fp_g_value_get_int64 = dl_symbol("g_value_get_int64");545fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64");546fp_g_value_get_float = dl_symbol("g_value_get_float");547fp_g_value_get_double = dl_symbol("g_value_get_double");548fp_g_value_get_string = dl_symbol("g_value_get_string");549fp_g_value_get_enum = dl_symbol("g_value_get_enum");550fp_g_value_get_flags = dl_symbol("g_value_get_flags");551fp_g_value_get_param = dl_symbol("g_value_get_param");552fp_g_value_get_boxed = dl_symbol("g_value_get_boxed");553fp_g_value_get_pointer = dl_symbol("g_value_get_pointer");554fp_g_value_get_object = dl_symbol("g_value_get_object");555fp_g_param_spec_int = dl_symbol("g_param_spec_int");556fp_g_object_get = dl_symbol("g_object_get");557fp_g_object_set = dl_symbol("g_object_set");558559/* GDK */560fp_gdk_get_default_root_window =561dl_symbol("gdk_get_default_root_window");562fp_gdk_pixmap_new = dl_symbol("gdk_pixmap_new");563fp_gdk_pixbuf_get_from_drawable =564dl_symbol("gdk_pixbuf_get_from_drawable");565fp_gdk_pixbuf_scale_simple =566dl_symbol("gdk_pixbuf_scale_simple");567fp_gdk_gc_new = dl_symbol("gdk_gc_new");568fp_gdk_rgb_gc_set_foreground =569dl_symbol("gdk_rgb_gc_set_foreground");570fp_gdk_draw_rectangle = dl_symbol("gdk_draw_rectangle");571fp_gdk_drawable_get_size = dl_symbol("gdk_drawable_get_size");572573/* Pixbuf */574fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new");575fp_gdk_pixbuf_new_from_file =576dl_symbol("gdk_pixbuf_new_from_file");577fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width");578fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height");579fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels");580fp_gdk_pixbuf_get_rowstride =581dl_symbol("gdk_pixbuf_get_rowstride");582fp_gdk_pixbuf_get_has_alpha =583dl_symbol("gdk_pixbuf_get_has_alpha");584fp_gdk_pixbuf_get_bits_per_sample =585dl_symbol("gdk_pixbuf_get_bits_per_sample");586fp_gdk_pixbuf_get_n_channels =587dl_symbol("gdk_pixbuf_get_n_channels");588fp_gdk_pixbuf_get_colorspace =589dl_symbol("gdk_pixbuf_get_colorspace");590591/* GTK painting */592fp_gtk_init_check = dl_symbol("gtk_init_check");593fp_gtk_paint_hline = dl_symbol("gtk_paint_hline");594fp_gtk_paint_vline = dl_symbol("gtk_paint_vline");595fp_gtk_paint_shadow = dl_symbol("gtk_paint_shadow");596fp_gtk_paint_arrow = dl_symbol("gtk_paint_arrow");597fp_gtk_paint_diamond = dl_symbol("gtk_paint_diamond");598fp_gtk_paint_box = dl_symbol("gtk_paint_box");599fp_gtk_paint_flat_box = dl_symbol("gtk_paint_flat_box");600fp_gtk_paint_check = dl_symbol("gtk_paint_check");601fp_gtk_paint_option = dl_symbol("gtk_paint_option");602fp_gtk_paint_box_gap = dl_symbol("gtk_paint_box_gap");603fp_gtk_paint_extension = dl_symbol("gtk_paint_extension");604fp_gtk_paint_focus = dl_symbol("gtk_paint_focus");605fp_gtk_paint_slider = dl_symbol("gtk_paint_slider");606fp_gtk_paint_handle = dl_symbol("gtk_paint_handle");607fp_gtk_paint_expander = dl_symbol("gtk_paint_expander");608fp_gtk_style_apply_default_background =609dl_symbol("gtk_style_apply_default_background");610611/* GTK widgets */612fp_gtk_arrow_new = dl_symbol("gtk_arrow_new");613fp_gtk_button_new = dl_symbol("gtk_button_new");614fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new");615fp_gtk_check_button_new = dl_symbol("gtk_check_button_new");616fp_gtk_check_menu_item_new =617dl_symbol("gtk_check_menu_item_new");618fp_gtk_color_selection_dialog_new =619dl_symbol("gtk_color_selection_dialog_new");620fp_gtk_entry_new = dl_symbol("gtk_entry_new");621fp_gtk_fixed_new = dl_symbol("gtk_fixed_new");622fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new");623fp_gtk_image_new = dl_symbol("gtk_image_new");624fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new");625fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new");626fp_gtk_hscale_new = dl_symbol("gtk_hscale_new");627fp_gtk_vscale_new = dl_symbol("gtk_vscale_new");628fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new");629fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new");630fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new");631fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new");632fp_gtk_label_new = dl_symbol("gtk_label_new");633fp_gtk_menu_new = dl_symbol("gtk_menu_new");634fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new");635fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new");636fp_gtk_menu_item_set_submenu =637dl_symbol("gtk_menu_item_set_submenu");638fp_gtk_notebook_new = dl_symbol("gtk_notebook_new");639fp_gtk_progress_bar_new =640dl_symbol("gtk_progress_bar_new");641fp_gtk_progress_bar_set_orientation =642dl_symbol("gtk_progress_bar_set_orientation");643fp_gtk_radio_button_new =644dl_symbol("gtk_radio_button_new");645fp_gtk_radio_menu_item_new =646dl_symbol("gtk_radio_menu_item_new");647fp_gtk_scrolled_window_new =648dl_symbol("gtk_scrolled_window_new");649fp_gtk_separator_menu_item_new =650dl_symbol("gtk_separator_menu_item_new");651fp_gtk_text_view_new = dl_symbol("gtk_text_view_new");652fp_gtk_toggle_button_new =653dl_symbol("gtk_toggle_button_new");654fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new");655fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new");656fp_gtk_viewport_new = dl_symbol("gtk_viewport_new");657fp_gtk_window_new = dl_symbol("gtk_window_new");658fp_gtk_window_present = dl_symbol("gtk_window_present");659fp_gtk_window_move = dl_symbol("gtk_window_move");660fp_gtk_window_resize = dl_symbol("gtk_window_resize");661662fp_gtk_dialog_new = dl_symbol("gtk_dialog_new");663fp_gtk_frame_new = dl_symbol("gtk_frame_new");664665fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new");666fp_gtk_container_add = dl_symbol("gtk_container_add");667fp_gtk_menu_shell_append =668dl_symbol("gtk_menu_shell_append");669fp_gtk_widget_realize = dl_symbol("gtk_widget_realize");670fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy");671fp_gtk_widget_render_icon =672dl_symbol("gtk_widget_render_icon");673fp_gtk_widget_set_name =674dl_symbol("gtk_widget_set_name");675fp_gtk_widget_set_parent =676dl_symbol("gtk_widget_set_parent");677fp_gtk_widget_set_direction =678dl_symbol("gtk_widget_set_direction");679fp_gtk_widget_style_get =680dl_symbol("gtk_widget_style_get");681fp_gtk_widget_class_install_style_property =682dl_symbol("gtk_widget_class_install_style_property");683fp_gtk_widget_class_find_style_property =684dl_symbol("gtk_widget_class_find_style_property");685fp_gtk_widget_style_get_property =686dl_symbol("gtk_widget_style_get_property");687fp_pango_font_description_to_string =688dl_symbol("pango_font_description_to_string");689fp_gtk_settings_get_default =690dl_symbol("gtk_settings_get_default");691fp_gtk_widget_get_settings =692dl_symbol("gtk_widget_get_settings");693fp_gtk_border_get_type = dl_symbol("gtk_border_get_type");694fp_gtk_arrow_set = dl_symbol("gtk_arrow_set");695fp_gtk_widget_size_request =696dl_symbol("gtk_widget_size_request");697fp_gtk_range_get_adjustment =698dl_symbol("gtk_range_get_adjustment");699700fp_gtk_widget_hide = dl_symbol("gtk_widget_hide");701fp_gtk_main_quit = dl_symbol("gtk_main_quit");702fp_g_signal_connect_data = dl_symbol("g_signal_connect_data");703fp_gtk_widget_show = dl_symbol("gtk_widget_show");704fp_gtk_main = dl_symbol("gtk_main");705706fp_g_path_get_dirname = dl_symbol("g_path_get_dirname");707708/**709* GLib thread system710*/711if (GLIB_CHECK_VERSION(2, 20, 0)) {712fp_g_thread_get_initialized = dl_symbol_gthread("g_thread_get_initialized");713}714fp_g_thread_init = dl_symbol_gthread("g_thread_init");715fp_gdk_threads_init = dl_symbol("gdk_threads_init");716fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");717fp_gdk_threads_leave = dl_symbol("gdk_threads_leave");718719/**720* Functions for sun_awt_X11_GtkFileDialogPeer.c721*/722if (fp_gtk_check_version(2, 4, 0) == NULL) {723// The current GtkFileChooser is available from GTK+ 2.4724gtk2_file_chooser_load();725}726727/* Some functions may be missing in pre-2.4 GTK.728We handle them specially here.729*/730fp_gtk_combo_box_new = dlsym(gtk2_libhandle, "gtk_combo_box_new");731if (fp_gtk_combo_box_new == NULL) {732fp_gtk_combo_box_new = dl_symbol("gtk_combo_new");733}734735fp_gtk_combo_box_entry_new =736dlsym(gtk2_libhandle, "gtk_combo_box_entry_new");737if (fp_gtk_combo_box_entry_new == NULL) {738fp_gtk_combo_box_entry_new = dl_symbol("gtk_combo_new");739new_combo = FALSE;740}741742fp_gtk_separator_tool_item_new =743dlsym(gtk2_libhandle, "gtk_separator_tool_item_new");744if (fp_gtk_separator_tool_item_new == NULL) {745fp_gtk_separator_tool_item_new =746dl_symbol("gtk_vseparator_new");747}748749fp_g_list_append = dl_symbol("g_list_append");750fp_g_list_free = dl_symbol("g_list_free");751fp_g_list_free_full = dl_symbol("g_list_free_full");752}753/* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION754* Otherwise we can check the return value of setjmp method.755*/756else757{758dlclose(gtk2_libhandle);759gtk2_libhandle = NULL;760761dlclose(gthread_libhandle);762gthread_libhandle = NULL;763764return FALSE;765}766767/*768* Strip the AT-SPI GTK_MODULES if present769*/770gtk_modules_env = getenv ("GTK_MODULES");771if ((gtk_modules_env && strstr(gtk_modules_env, "atk-bridge")) ||772(gtk_modules_env && strstr(gtk_modules_env, "gail"))) {773/* careful, strtok modifies its args */774gchar *tmp_env = strdup(gtk_modules_env);775if (tmp_env) {776/* the new env will be smaller than the old one */777gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc,778sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env));779780if (new_env) {781strcpy(new_env, ENV_PREFIX);782783/* strip out 'atk-bridge' and 'gail' */784size_t PREFIX_LENGTH = strlen(ENV_PREFIX);785gchar *tmp_ptr = NULL;786for (s = strtok_r(tmp_env, ":", &tmp_ptr); s;787s = strtok_r(NULL, ":", &tmp_ptr)) {788if ((!strstr(s, "atk-bridge")) && (!strstr(s, "gail"))) {789if (strlen(new_env) > PREFIX_LENGTH) {790new_env = strcat(new_env, ":");791}792new_env = strcat(new_env, s);793}794}795if (putenv(new_env) != 0) {796/* no free() on success, putenv() doesn't copy string */797free(new_env);798}799}800free(tmp_env);801}802}803/*804* GTK should be initialized with gtk_init_check() before use.805*806* gtk_init_check installs its own error handlers. It is critical that807* we preserve error handler set from AWT. Otherwise we'll crash on808* BadMatch errors which we would normally ignore. The IO error handler809* is preserved here, too, just for consistency.810*/811AWT_LOCK();812handler = XSetErrorHandler(NULL);813io_handler = XSetIOErrorHandler(NULL);814815if (fp_gtk_check_version(2, 2, 0) == NULL) {816817// Calling g_thread_init() multiple times leads to crash on GLib < 2.24818// We can use g_thread_get_initialized () but it is available only for819// GLib >= 2.20.820gboolean is_g_thread_get_initialized = FALSE;821if (GLIB_CHECK_VERSION(2, 20, 0)) {822is_g_thread_get_initialized = fp_g_thread_get_initialized();823}824825if (!is_g_thread_get_initialized) {826fp_g_thread_init(NULL);827}828829//According the GTK documentation, gdk_threads_init() should be830//called before gtk_init() or gtk_init_check()831fp_gdk_threads_init();832}833result = (*fp_gtk_init_check)(NULL, NULL);834835XSetErrorHandler(handler);836XSetIOErrorHandler(io_handler);837AWT_UNLOCK();838839/* Initialize widget array. */840for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)841{842gtk2_widgets[i] = NULL;843}844if (result) {845GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi));846gtk2_init(gtk);847return gtk;848}849return NULL;850}851852int gtk2_unload()853{854int i;855char *gtk2_error;856857if (!gtk2_libhandle)858return TRUE;859860/* Release painting objects */861if (gtk2_white_pixmap != NULL) {862(*fp_g_object_unref)(gtk2_white_pixmap);863(*fp_g_object_unref)(gtk2_black_pixmap);864(*fp_g_object_unref)(gtk2_white_pixbuf);865(*fp_g_object_unref)(gtk2_black_pixbuf);866gtk2_white_pixmap = gtk2_black_pixmap =867gtk2_white_pixbuf = gtk2_black_pixbuf = NULL;868}869gtk2_pixbuf_width = 0;870gtk2_pixbuf_height = 0;871872if (gtk2_window != NULL) {873/* Destroying toplevel widget will destroy all contained widgets */874(*fp_gtk_widget_destroy)(gtk2_window);875876/* Unset some static data so they get reinitialized on next load */877gtk2_window = NULL;878}879880dlerror();881dlclose(gtk2_libhandle);882dlclose(gthread_libhandle);883if ((gtk2_error = dlerror()) != NULL)884{885return FALSE;886}887return TRUE;888}889890/* Dispatch all pending events from the GTK event loop.891* This is needed to catch theme change and update widgets' style.892*/893static void flush_gtk_event_loop()894{895while( (*fp_g_main_context_iteration)(NULL, FALSE));896}897898/*899* Initialize components of containment hierarchy. This creates a GtkFixed900* inside a GtkWindow. All widgets get realized.901*/902static void init_containers()903{904if (gtk2_window == NULL)905{906gtk2_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);907gtk2_fixed = (GtkFixed *)(*fp_gtk_fixed_new)();908(*fp_gtk_container_add)((GtkContainer*)gtk2_window,909(GtkWidget *)gtk2_fixed);910(*fp_gtk_widget_realize)(gtk2_window);911(*fp_gtk_widget_realize)((GtkWidget *)gtk2_fixed);912}913}914915/*916* Ensure everything is ready for drawing an element of the specified width917* and height.918*919* We should somehow handle translucent images. GTK can draw to X Drawables920* only, which don't support alpha. When we retrieve the image back from921* the server, translucency information is lost. There're several ways to922* work around this:923* 1) Subclass GdkPixmap and cache translucent objects on client side. This924* requires us to implement parts of X server drawing logic on client side.925* Many X requests can potentially be "translucent"; e.g. XDrawLine with926* fill=tile and a translucent tile is a "translucent" operation, whereas927* XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some928* do) intermix transparent and opaque operations which makes caching even929* more problematic.930* 2) Use Xorg 32bit ARGB visual when available. GDK has no native support931* for it (as of version 2.6). Also even in JDS 3 Xorg does not support932* these visuals by default, which makes optimizing for them pointless.933* We can consider doing this at a later point when ARGB visuals become more934* popular.935* 3') GTK has plans to use Cairo as its graphical backend (presumably in936* 2.8), and Cairo supports alpha. With it we could also get rid of the937* unnecessary round trip to server and do all the drawing on client side.938* 4) For now we draw to two different pixmaps and restore alpha channel by939* comparing results. This can be optimized by using subclassed pixmap and940* doing the second drawing only if necessary.941*/942static void gtk2_init_painting(JNIEnv *env, gint width, gint height)943{944GdkGC *gc;945GdkPixbuf *white, *black;946947init_containers();948949if (gtk2_pixbuf_width < width || gtk2_pixbuf_height < height)950{951white = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);952black = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);953954if (white == NULL || black == NULL)955{956snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height);957throw_exception(env, "java/lang/RuntimeException", convertionBuffer);958fp_gdk_threads_leave();959return;960}961962if (gtk2_white_pixmap != NULL) {963/* free old stuff */964(*fp_g_object_unref)(gtk2_white_pixmap);965(*fp_g_object_unref)(gtk2_black_pixmap);966(*fp_g_object_unref)(gtk2_white_pixbuf);967(*fp_g_object_unref)(gtk2_black_pixbuf);968}969970gtk2_white_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1);971gtk2_black_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1);972973gtk2_white_pixbuf = white;974gtk2_black_pixbuf = black;975976gtk2_pixbuf_width = width;977gtk2_pixbuf_height = height;978}979980/* clear the pixmaps */981gc = (*fp_gdk_gc_new)(gtk2_white_pixmap);982(*fp_gdk_rgb_gc_set_foreground)(gc, 0xffffff);983(*fp_gdk_draw_rectangle)(gtk2_white_pixmap, gc, TRUE, 0, 0, width, height);984(*fp_g_object_unref)(gc);985986gc = (*fp_gdk_gc_new)(gtk2_black_pixmap);987(*fp_gdk_rgb_gc_set_foreground)(gc, 0x000000);988(*fp_gdk_draw_rectangle)(gtk2_black_pixmap, gc, TRUE, 0, 0, width, height);989(*fp_g_object_unref)(gc);990}991992/*993* Restore image from white and black pixmaps and copy it into destination994* buffer. This method compares two pixbufs taken from white and black995* pixmaps and decodes color and alpha components. Pixbufs are RGB without996* alpha, destination buffer is ABGR.997*998* The return value is the transparency type of the resulting image, either999* one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and1000* java_awt_Transparency_TRANSLUCENT.1001*/1002static gint gtk2_copy_image(gint *dst, gint width, gint height)1003{1004gint i, j, r, g, b;1005guchar *white, *black;1006gint stride, padding;1007gboolean is_opaque = TRUE;1008gboolean is_bitmask = TRUE;10091010(*fp_gdk_pixbuf_get_from_drawable)(gtk2_white_pixbuf, gtk2_white_pixmap,1011NULL, 0, 0, 0, 0, width, height);1012(*fp_gdk_pixbuf_get_from_drawable)(gtk2_black_pixbuf, gtk2_black_pixmap,1013NULL, 0, 0, 0, 0, width, height);10141015white = (*fp_gdk_pixbuf_get_pixels)(gtk2_white_pixbuf);1016black = (*fp_gdk_pixbuf_get_pixels)(gtk2_black_pixbuf);1017stride = (*fp_gdk_pixbuf_get_rowstride)(gtk2_black_pixbuf);1018padding = stride - width * 4;1019if (padding >= 0 && stride > 0) {1020for (i = 0; i < height; i++) {1021for (j = 0; j < width; j++) {1022int r1 = *white++;1023int r2 = *black++;1024int alpha = 0xff + r2 - r1;10251026switch (alpha) {1027case 0: /* transparent pixel */1028r = g = b = 0;1029black += 3;1030white += 3;1031is_opaque = FALSE;1032break;10331034case 0xff: /* opaque pixel */1035r = r2;1036g = *black++;1037b = *black++;1038black++;1039white += 3;1040break;10411042default: /* translucent pixel */1043r = 0xff * r2 / alpha;1044g = 0xff * *black++ / alpha;1045b = 0xff * *black++ / alpha;1046black++;1047white += 3;1048is_opaque = FALSE;1049is_bitmask = FALSE;1050break;1051}10521053*dst++ = (alpha << 24 | r << 16 | g << 8 | b);1054}10551056white += padding;1057black += padding;1058}1059}1060return is_opaque ? java_awt_Transparency_OPAQUE :1061(is_bitmask ? java_awt_Transparency_BITMASK :1062java_awt_Transparency_TRANSLUCENT);1063}10641065static void1066gtk2_set_direction(GtkWidget *widget, GtkTextDirection dir)1067{1068/*1069* Some engines (inexplicably) look at the direction of the widget's1070* parent, so we need to set the direction of both the widget and its1071* parent.1072*/1073(*fp_gtk_widget_set_direction)(widget, dir);1074if (widget->parent != NULL) {1075(*fp_gtk_widget_set_direction)(widget->parent, dir);1076}1077}10781079/*1080* Initializes the widget to correct state for some engines.1081* This is a pure empirical method.1082*/1083static void init_toggle_widget(WidgetType widget_type, gint synth_state)1084{1085gboolean is_active = ((synth_state & SELECTED) != 0);10861087if (widget_type == RADIO_BUTTON ||1088widget_type == CHECK_BOX ||1089widget_type == TOGGLE_BUTTON) {1090((GtkToggleButton*)gtk2_widget)->active = is_active;1091}10921093if ((synth_state & FOCUSED) != 0) {1094((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;1095} else {1096((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;1097}10981099if ((synth_state & MOUSE_OVER) != 0 && (synth_state & PRESSED) == 0 ||1100(synth_state & FOCUSED) != 0 && (synth_state & PRESSED) != 0) {1101gtk2_widget->state = GTK_STATE_PRELIGHT;1102} else if ((synth_state & DISABLED) != 0) {1103gtk2_widget->state = GTK_STATE_INSENSITIVE;1104} else {1105gtk2_widget->state = is_active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL;1106}1107}11081109/* GTK state_type filter */1110static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state)1111{1112GtkStateType result = GTK_STATE_NORMAL;11131114if ((synth_state & DISABLED) != 0) {1115result = GTK_STATE_INSENSITIVE;1116} else if ((synth_state & PRESSED) != 0) {1117result = GTK_STATE_ACTIVE;1118} else if ((synth_state & MOUSE_OVER) != 0) {1119result = GTK_STATE_PRELIGHT;1120}1121return result;1122}11231124/* GTK shadow_type filter */1125static GtkShadowType get_gtk_shadow_type(WidgetType widget_type, gint synth_state)1126{1127GtkShadowType result = GTK_SHADOW_OUT;11281129if ((synth_state & SELECTED) != 0) {1130result = GTK_SHADOW_IN;1131}1132return result;1133}113411351136static GtkWidget* gtk2_get_arrow(GtkArrowType arrow_type, GtkShadowType shadow_type)1137{1138GtkWidget *arrow = NULL;1139if (NULL == gtk2_widgets[_GTK_ARROW_TYPE])1140{1141gtk2_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type, shadow_type);1142(*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, gtk2_widgets[_GTK_ARROW_TYPE]);1143(*fp_gtk_widget_realize)(gtk2_widgets[_GTK_ARROW_TYPE]);1144}1145arrow = gtk2_widgets[_GTK_ARROW_TYPE];11461147(*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type);1148return arrow;1149}11501151static GtkAdjustment* create_adjustment()1152{1153return (GtkAdjustment *)1154(*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0);1155}11561157/**1158* Returns a pointer to the cached native widget for the specified widget1159* type.1160*/1161static GtkWidget *gtk2_get_widget(WidgetType widget_type)1162{1163gboolean init_result = FALSE;1164GtkWidget *result = NULL;1165switch (widget_type)1166{1167case BUTTON:1168case TABLE_HEADER:1169if (init_result = (NULL == gtk2_widgets[_GTK_BUTTON_TYPE]))1170{1171gtk2_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)();1172}1173result = gtk2_widgets[_GTK_BUTTON_TYPE];1174break;1175case CHECK_BOX:1176if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_BUTTON_TYPE]))1177{1178gtk2_widgets[_GTK_CHECK_BUTTON_TYPE] =1179(*fp_gtk_check_button_new)();1180}1181result = gtk2_widgets[_GTK_CHECK_BUTTON_TYPE];1182break;1183case CHECK_BOX_MENU_ITEM:1184if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE]))1185{1186gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE] =1187(*fp_gtk_check_menu_item_new)();1188}1189result = gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE];1190break;1191/************************************************************1192* Creation a dedicated color chooser is dangerous because1193* it deadlocks the EDT1194************************************************************/1195/* case COLOR_CHOOSER:1196if (init_result =1197(NULL == gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]))1198{1199gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] =1200(*fp_gtk_color_selection_dialog_new)(NULL);1201}1202result = gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE];1203break;*/1204case COMBO_BOX:1205if (init_result = (NULL == gtk2_widgets[_GTK_COMBO_BOX_TYPE]))1206{1207gtk2_widgets[_GTK_COMBO_BOX_TYPE] =1208(*fp_gtk_combo_box_new)();1209}1210result = gtk2_widgets[_GTK_COMBO_BOX_TYPE];1211break;1212case COMBO_BOX_ARROW_BUTTON:1213if (init_result =1214(NULL == gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]))1215{1216gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] =1217(*fp_gtk_toggle_button_new)();1218}1219result = gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE];1220break;1221case COMBO_BOX_TEXT_FIELD:1222if (init_result =1223(NULL == gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]))1224{1225result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] =1226(*fp_gtk_entry_new)();1227}1228result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE];1229break;1230case DESKTOP_ICON:1231case INTERNAL_FRAME_TITLE_PANE:1232case LABEL:1233if (init_result = (NULL == gtk2_widgets[_GTK_LABEL_TYPE]))1234{1235gtk2_widgets[_GTK_LABEL_TYPE] =1236(*fp_gtk_label_new)(NULL);1237}1238result = gtk2_widgets[_GTK_LABEL_TYPE];1239break;1240case DESKTOP_PANE:1241case PANEL:1242case ROOT_PANE:1243if (init_result = (NULL == gtk2_widgets[_GTK_CONTAINER_TYPE]))1244{1245/* There is no constructor for a container type. I've1246* chosen GtkFixed container since it has a default1247* constructor.1248*/1249gtk2_widgets[_GTK_CONTAINER_TYPE] =1250(*fp_gtk_fixed_new)();1251}1252result = gtk2_widgets[_GTK_CONTAINER_TYPE];1253break;1254case EDITOR_PANE:1255case TEXT_AREA:1256case TEXT_PANE:1257if (init_result = (NULL == gtk2_widgets[_GTK_TEXT_VIEW_TYPE]))1258{1259gtk2_widgets[_GTK_TEXT_VIEW_TYPE] =1260(*fp_gtk_text_view_new)();1261}1262result = gtk2_widgets[_GTK_TEXT_VIEW_TYPE];1263break;1264case FORMATTED_TEXT_FIELD:1265case PASSWORD_FIELD:1266case TEXT_FIELD:1267if (init_result = (NULL == gtk2_widgets[_GTK_ENTRY_TYPE]))1268{1269gtk2_widgets[_GTK_ENTRY_TYPE] =1270(*fp_gtk_entry_new)();1271}1272result = gtk2_widgets[_GTK_ENTRY_TYPE];1273break;1274case HANDLE_BOX:1275if (init_result = (NULL == gtk2_widgets[_GTK_HANDLE_BOX_TYPE]))1276{1277gtk2_widgets[_GTK_HANDLE_BOX_TYPE] =1278(*fp_gtk_handle_box_new)();1279}1280result = gtk2_widgets[_GTK_HANDLE_BOX_TYPE];1281break;1282case HSCROLL_BAR:1283case HSCROLL_BAR_BUTTON_LEFT:1284case HSCROLL_BAR_BUTTON_RIGHT:1285case HSCROLL_BAR_TRACK:1286case HSCROLL_BAR_THUMB:1287if (init_result = (NULL == gtk2_widgets[_GTK_HSCROLLBAR_TYPE]))1288{1289gtk2_widgets[_GTK_HSCROLLBAR_TYPE] =1290(*fp_gtk_hscrollbar_new)(create_adjustment());1291}1292result = gtk2_widgets[_GTK_HSCROLLBAR_TYPE];1293break;1294case HSEPARATOR:1295if (init_result = (NULL == gtk2_widgets[_GTK_HSEPARATOR_TYPE]))1296{1297gtk2_widgets[_GTK_HSEPARATOR_TYPE] =1298(*fp_gtk_hseparator_new)();1299}1300result = gtk2_widgets[_GTK_HSEPARATOR_TYPE];1301break;1302case HSLIDER:1303case HSLIDER_THUMB:1304case HSLIDER_TRACK:1305if (init_result = (NULL == gtk2_widgets[_GTK_HSCALE_TYPE]))1306{1307gtk2_widgets[_GTK_HSCALE_TYPE] =1308(*fp_gtk_hscale_new)(NULL);1309}1310result = gtk2_widgets[_GTK_HSCALE_TYPE];1311break;1312case HSPLIT_PANE_DIVIDER:1313case SPLIT_PANE:1314if (init_result = (NULL == gtk2_widgets[_GTK_HPANED_TYPE]))1315{1316gtk2_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)();1317}1318result = gtk2_widgets[_GTK_HPANED_TYPE];1319break;1320case IMAGE:1321if (init_result = (NULL == gtk2_widgets[_GTK_IMAGE_TYPE]))1322{1323gtk2_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)();1324}1325result = gtk2_widgets[_GTK_IMAGE_TYPE];1326break;1327case INTERNAL_FRAME:1328if (init_result = (NULL == gtk2_widgets[_GTK_WINDOW_TYPE]))1329{1330gtk2_widgets[_GTK_WINDOW_TYPE] =1331(*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);1332}1333result = gtk2_widgets[_GTK_WINDOW_TYPE];1334break;1335case TOOL_TIP:1336if (init_result = (NULL == gtk2_widgets[_GTK_TOOLTIP_TYPE]))1337{1338result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);1339(*fp_gtk_widget_set_name)(result, "gtk-tooltips");1340gtk2_widgets[_GTK_TOOLTIP_TYPE] = result;1341}1342result = gtk2_widgets[_GTK_TOOLTIP_TYPE];1343break;1344case LIST:1345case TABLE:1346case TREE:1347case TREE_CELL:1348if (init_result = (NULL == gtk2_widgets[_GTK_TREE_VIEW_TYPE]))1349{1350gtk2_widgets[_GTK_TREE_VIEW_TYPE] =1351(*fp_gtk_tree_view_new)();1352}1353result = gtk2_widgets[_GTK_TREE_VIEW_TYPE];1354break;1355case TITLED_BORDER:1356if (init_result = (NULL == gtk2_widgets[_GTK_FRAME_TYPE]))1357{1358gtk2_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL);1359}1360result = gtk2_widgets[_GTK_FRAME_TYPE];1361break;1362case POPUP_MENU:1363if (init_result = (NULL == gtk2_widgets[_GTK_MENU_TYPE]))1364{1365gtk2_widgets[_GTK_MENU_TYPE] =1366(*fp_gtk_menu_new)();1367}1368result = gtk2_widgets[_GTK_MENU_TYPE];1369break;1370case MENU:1371case MENU_ITEM:1372case MENU_ITEM_ACCELERATOR:1373if (init_result = (NULL == gtk2_widgets[_GTK_MENU_ITEM_TYPE]))1374{1375gtk2_widgets[_GTK_MENU_ITEM_TYPE] =1376(*fp_gtk_menu_item_new)();1377}1378result = gtk2_widgets[_GTK_MENU_ITEM_TYPE];1379break;1380case MENU_BAR:1381if (init_result = (NULL == gtk2_widgets[_GTK_MENU_BAR_TYPE]))1382{1383gtk2_widgets[_GTK_MENU_BAR_TYPE] =1384(*fp_gtk_menu_bar_new)();1385}1386result = gtk2_widgets[_GTK_MENU_BAR_TYPE];1387break;1388case COLOR_CHOOSER:1389case OPTION_PANE:1390if (init_result = (NULL == gtk2_widgets[_GTK_DIALOG_TYPE]))1391{1392gtk2_widgets[_GTK_DIALOG_TYPE] =1393(*fp_gtk_dialog_new)();1394}1395result = gtk2_widgets[_GTK_DIALOG_TYPE];1396break;1397case POPUP_MENU_SEPARATOR:1398if (init_result =1399(NULL == gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]))1400{1401gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] =1402(*fp_gtk_separator_menu_item_new)();1403}1404result = gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE];1405break;1406case HPROGRESS_BAR:1407if (init_result = (NULL == gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE]))1408{1409gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE] =1410(*fp_gtk_progress_bar_new)();1411}1412result = gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE];1413break;1414case VPROGRESS_BAR:1415if (init_result = (NULL == gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE]))1416{1417gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE] =1418(*fp_gtk_progress_bar_new)();1419/*1420* Vertical JProgressBars always go bottom-to-top,1421* regardless of the ComponentOrientation.1422*/1423(*fp_gtk_progress_bar_set_orientation)(1424(GtkProgressBar *)gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE],1425GTK_PROGRESS_BOTTOM_TO_TOP);1426}1427result = gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE];1428break;1429case RADIO_BUTTON:1430if (init_result = (NULL == gtk2_widgets[_GTK_RADIO_BUTTON_TYPE]))1431{1432gtk2_widgets[_GTK_RADIO_BUTTON_TYPE] =1433(*fp_gtk_radio_button_new)(NULL);1434}1435result = gtk2_widgets[_GTK_RADIO_BUTTON_TYPE];1436break;1437case RADIO_BUTTON_MENU_ITEM:1438if (init_result =1439(NULL == gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE]))1440{1441gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE] =1442(*fp_gtk_radio_menu_item_new)(NULL);1443}1444result = gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE];1445break;1446case SCROLL_PANE:1447if (init_result =1448(NULL == gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE]))1449{1450gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE] =1451(*fp_gtk_scrolled_window_new)(NULL, NULL);1452}1453result = gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE];1454break;1455case SPINNER:1456case SPINNER_ARROW_BUTTON:1457case SPINNER_TEXT_FIELD:1458if (init_result = (NULL == gtk2_widgets[_GTK_SPIN_BUTTON_TYPE]))1459{1460result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE] =1461(*fp_gtk_spin_button_new)(NULL, 0, 0);1462}1463result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE];1464break;1465case TABBED_PANE:1466case TABBED_PANE_TAB_AREA:1467case TABBED_PANE_CONTENT:1468case TABBED_PANE_TAB:1469if (init_result = (NULL == gtk2_widgets[_GTK_NOTEBOOK_TYPE]))1470{1471gtk2_widgets[_GTK_NOTEBOOK_TYPE] =1472(*fp_gtk_notebook_new)(NULL);1473}1474result = gtk2_widgets[_GTK_NOTEBOOK_TYPE];1475break;1476case TOGGLE_BUTTON:1477if (init_result = (NULL == gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE]))1478{1479gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE] =1480(*fp_gtk_toggle_button_new)(NULL);1481}1482result = gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE];1483break;1484case TOOL_BAR:1485case TOOL_BAR_DRAG_WINDOW:1486if (init_result = (NULL == gtk2_widgets[_GTK_TOOLBAR_TYPE]))1487{1488gtk2_widgets[_GTK_TOOLBAR_TYPE] =1489(*fp_gtk_toolbar_new)(NULL);1490}1491result = gtk2_widgets[_GTK_TOOLBAR_TYPE];1492break;1493case TOOL_BAR_SEPARATOR:1494if (init_result =1495(NULL == gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]))1496{1497gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] =1498(*fp_gtk_separator_tool_item_new)();1499}1500result = gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE];1501break;1502case VIEWPORT:1503if (init_result = (NULL == gtk2_widgets[_GTK_VIEWPORT_TYPE]))1504{1505GtkAdjustment *adjustment = create_adjustment();1506gtk2_widgets[_GTK_VIEWPORT_TYPE] =1507(*fp_gtk_viewport_new)(adjustment, adjustment);1508}1509result = gtk2_widgets[_GTK_VIEWPORT_TYPE];1510break;1511case VSCROLL_BAR:1512case VSCROLL_BAR_BUTTON_UP:1513case VSCROLL_BAR_BUTTON_DOWN:1514case VSCROLL_BAR_TRACK:1515case VSCROLL_BAR_THUMB:1516if (init_result = (NULL == gtk2_widgets[_GTK_VSCROLLBAR_TYPE]))1517{1518gtk2_widgets[_GTK_VSCROLLBAR_TYPE] =1519(*fp_gtk_vscrollbar_new)(create_adjustment());1520}1521result = gtk2_widgets[_GTK_VSCROLLBAR_TYPE];1522break;1523case VSEPARATOR:1524if (init_result = (NULL == gtk2_widgets[_GTK_VSEPARATOR_TYPE]))1525{1526gtk2_widgets[_GTK_VSEPARATOR_TYPE] =1527(*fp_gtk_vseparator_new)();1528}1529result = gtk2_widgets[_GTK_VSEPARATOR_TYPE];1530break;1531case VSLIDER:1532case VSLIDER_THUMB:1533case VSLIDER_TRACK:1534if (init_result = (NULL == gtk2_widgets[_GTK_VSCALE_TYPE]))1535{1536gtk2_widgets[_GTK_VSCALE_TYPE] =1537(*fp_gtk_vscale_new)(NULL);1538}1539result = gtk2_widgets[_GTK_VSCALE_TYPE];1540/*1541* Vertical JSliders start at the bottom, while vertical1542* GtkVScale widgets start at the top (by default), so to fix1543* this we set the "inverted" flag to get the Swing behavior.1544*/1545((GtkRange*)result)->inverted = 1;1546break;1547case VSPLIT_PANE_DIVIDER:1548if (init_result = (NULL == gtk2_widgets[_GTK_VPANED_TYPE]))1549{1550gtk2_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)();1551}1552result = gtk2_widgets[_GTK_VPANED_TYPE];1553break;1554default:1555result = NULL;1556break;1557}15581559if (result != NULL && init_result)1560{1561if (widget_type == RADIO_BUTTON_MENU_ITEM ||1562widget_type == CHECK_BOX_MENU_ITEM ||1563widget_type == MENU_ITEM ||1564widget_type == MENU ||1565widget_type == POPUP_MENU_SEPARATOR)1566{1567GtkWidget *menu = gtk2_get_widget(POPUP_MENU);1568(*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result);1569}1570else if (widget_type == POPUP_MENU)1571{1572GtkWidget *menu_bar = gtk2_get_widget(MENU_BAR);1573GtkWidget *root_menu = (*fp_gtk_menu_item_new)();1574(*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result);1575(*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu);1576}1577else if (widget_type == COMBO_BOX_ARROW_BUTTON ||1578widget_type == COMBO_BOX_TEXT_FIELD)1579{1580/*1581* We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry1582* in order to trick engines into thinking it's a real combobox1583* arrow button/text field.1584*/1585GtkWidget *combo = (*fp_gtk_combo_box_entry_new)();15861587if (new_combo && widget_type == COMBO_BOX_ARROW_BUTTON) {1588(*fp_gtk_widget_set_parent)(result, combo);1589((GtkBin*)combo)->child = result;1590} else {1591(*fp_gtk_container_add)((GtkContainer *)combo, result);1592}1593(*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, combo);1594}1595else if (widget_type != TOOL_TIP &&1596widget_type != INTERNAL_FRAME &&1597widget_type != OPTION_PANE)1598{1599(*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, result);1600}1601(*fp_gtk_widget_realize)(result);1602}1603return result;1604}16051606void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type,1607GtkShadowType shadow_type, const gchar *detail,1608gint x, gint y, gint width, gint height,1609GtkArrowType arrow_type, gboolean fill)1610{1611static int w, h;1612static GtkRequisition size;16131614if (widget_type == COMBO_BOX_ARROW_BUTTON || widget_type == TABLE)1615gtk2_widget = gtk2_get_arrow(arrow_type, shadow_type);1616else1617gtk2_widget = gtk2_get_widget(widget_type);16181619switch (widget_type)1620{1621case SPINNER_ARROW_BUTTON:1622x = 1;1623y = ((arrow_type == GTK_ARROW_UP) ? 2 : 0);1624height -= 2;1625width -= 3;16261627w = width / 2;1628w -= w % 2 - 1;1629h = (w + 1) / 2;1630break;16311632case HSCROLL_BAR_BUTTON_LEFT:1633case HSCROLL_BAR_BUTTON_RIGHT:1634case VSCROLL_BAR_BUTTON_UP:1635case VSCROLL_BAR_BUTTON_DOWN:1636w = width / 2;1637h = height / 2;1638break;16391640case COMBO_BOX_ARROW_BUTTON:1641case TABLE:1642x = 1;1643(*fp_gtk_widget_size_request)(gtk2_widget, &size);1644w = size.width - ((GtkMisc*)gtk2_widget)->xpad * 2;1645h = size.height - ((GtkMisc*)gtk2_widget)->ypad * 2;1646w = h = MIN(MIN(w, h), MIN(width,height)) * 0.7;1647break;16481649default:1650w = width;1651h = height;1652break;1653}1654x += (width - w) / 2;1655y += (height - h) / 2;16561657(*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_white_pixmap, state_type,1658shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,1659x, y, w, h);1660(*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_black_pixmap, state_type,1661shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,1662x, y, w, h);1663}16641665static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,1666GtkShadowType shadow_type, const gchar *detail,1667gint x, gint y, gint width, gint height,1668gint synth_state, GtkTextDirection dir)1669{1670gtk2_widget = gtk2_get_widget(widget_type);16711672/*1673* The clearlooks engine sometimes looks at the widget's state field1674* instead of just the state_type variable that we pass in, so to account1675* for those cases we set the widget's state field accordingly. The1676* flags field is similarly important for things like focus/default state.1677*/1678gtk2_widget->state = state_type;16791680if (widget_type == HSLIDER_TRACK) {1681/*1682* For horizontal JSliders with right-to-left orientation, we need1683* to set the "inverted" flag to match the native GTK behavior where1684* the foreground highlight is on the right side of the slider thumb.1685* This is needed especially for the ubuntulooks engine, which looks1686* exclusively at the "inverted" flag to determine on which side of1687* the thumb to paint the highlight...1688*/1689((GtkRange*)gtk2_widget)->inverted = (dir == GTK_TEXT_DIR_RTL);16901691/*1692* Note however that other engines like clearlooks will look at both1693* the "inverted" field and the text direction to determine how1694* the foreground highlight is painted:1695* !inverted && ltr --> paint highlight on left side1696* !inverted && rtl --> paint highlight on right side1697* inverted && ltr --> paint highlight on right side1698* inverted && rtl --> paint highlight on left side1699* So the only way to reliably get the desired results for horizontal1700* JSlider (i.e., highlight on left side for LTR ComponentOrientation1701* and highlight on right side for RTL ComponentOrientation) is to1702* always override text direction as LTR, and then set the "inverted"1703* flag accordingly (as we have done above).1704*/1705dir = GTK_TEXT_DIR_LTR;1706}17071708/*1709* Some engines (e.g. clearlooks) will paint the shadow of certain1710* widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the1711* the text direction.1712*/1713gtk2_set_direction(gtk2_widget, dir);17141715switch (widget_type) {1716case BUTTON:1717if (synth_state & DEFAULT) {1718((GtkObject*)gtk2_widget)->flags |= GTK_HAS_DEFAULT;1719} else {1720((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_DEFAULT;1721}1722break;1723case TOGGLE_BUTTON:1724init_toggle_widget(widget_type, synth_state);1725break;1726case HSCROLL_BAR_BUTTON_LEFT:1727/*1728* The clearlooks engine will draw a "left" button when:1729* x == w->allocation.x1730*1731* The ubuntulooks engine will draw a "left" button when:1732* [x,y,width,height]1733* intersects1734* [w->alloc.x,w->alloc.y,width,height]1735*1736* The values that are set below should ensure that a "left"1737* button is rendered for both of these (and other) engines.1738*/1739gtk2_widget->allocation.x = x;1740gtk2_widget->allocation.y = y;1741gtk2_widget->allocation.width = width;1742gtk2_widget->allocation.height = height;1743break;1744case HSCROLL_BAR_BUTTON_RIGHT:1745/*1746* The clearlooks engine will draw a "right" button when:1747* x + width == w->allocation.x + w->allocation.width1748*1749* The ubuntulooks engine will draw a "right" button when:1750* [x,y,width,height]1751* does not intersect1752* [w->alloc.x,w->alloc.y,width,height]1753* but does intersect1754* [w->alloc.x+width,w->alloc.y,width,height]1755*1756* The values that are set below should ensure that a "right"1757* button is rendered for both of these (and other) engines.1758*/1759gtk2_widget->allocation.x = x+width;1760gtk2_widget->allocation.y = 0;1761gtk2_widget->allocation.width = 0;1762gtk2_widget->allocation.height = height;1763break;1764case VSCROLL_BAR_BUTTON_UP:1765/*1766* The clearlooks engine will draw an "up" button when:1767* y == w->allocation.y1768*1769* The ubuntulooks engine will draw an "up" button when:1770* [x,y,width,height]1771* intersects1772* [w->alloc.x,w->alloc.y,width,height]1773*1774* The values that are set below should ensure that an "up"1775* button is rendered for both of these (and other) engines.1776*/1777gtk2_widget->allocation.x = x;1778gtk2_widget->allocation.y = y;1779gtk2_widget->allocation.width = width;1780gtk2_widget->allocation.height = height;1781break;1782case VSCROLL_BAR_BUTTON_DOWN:1783/*1784* The clearlooks engine will draw a "down" button when:1785* y + height == w->allocation.y + w->allocation.height1786*1787* The ubuntulooks engine will draw a "down" button when:1788* [x,y,width,height]1789* does not intersect1790* [w->alloc.x,w->alloc.y,width,height]1791* but does intersect1792* [w->alloc.x,w->alloc.y+height,width,height]1793*1794* The values that are set below should ensure that a "down"1795* button is rendered for both of these (and other) engines.1796*/1797gtk2_widget->allocation.x = x;1798gtk2_widget->allocation.y = y+height;1799gtk2_widget->allocation.width = width;1800gtk2_widget->allocation.height = 0;1801break;1802default:1803break;1804}18051806(*fp_gtk_paint_box)(gtk2_widget->style, gtk2_white_pixmap, state_type,1807shadow_type, NULL, gtk2_widget, detail, x, y, width, height);1808(*fp_gtk_paint_box)(gtk2_widget->style, gtk2_black_pixmap, state_type,1809shadow_type, NULL, gtk2_widget, detail, x, y, width, height);18101811/*1812* Reset the text direction to the default value so that we don't1813* accidentally affect other operations and widgets.1814*/1815gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);1816}18171818void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type,1819GtkShadowType shadow_type, const gchar *detail,1820gint x, gint y, gint width, gint height,1821GtkPositionType gap_side, gint gap_x, gint gap_width)1822{1823/* Clearlooks needs a real clip area to paint the gap properly */1824GdkRectangle area = { x, y, width, height };18251826gtk2_widget = gtk2_get_widget(widget_type);1827(*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_white_pixmap, state_type,1828shadow_type, &area, gtk2_widget, detail,1829x, y, width, height, gap_side, gap_x, gap_width);1830(*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_black_pixmap, state_type,1831shadow_type, &area, gtk2_widget, detail,1832x, y, width, height, gap_side, gap_x, gap_width);1833}18341835static void gtk2_paint_check(WidgetType widget_type, gint synth_state,1836const gchar *detail, gint x, gint y, gint width, gint height)1837{1838GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);1839GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);18401841gtk2_widget = gtk2_get_widget(widget_type);1842init_toggle_widget(widget_type, synth_state);18431844(*fp_gtk_paint_check)(gtk2_widget->style, gtk2_white_pixmap, state_type,1845shadow_type, NULL, gtk2_widget, detail,1846x, y, width, height);1847(*fp_gtk_paint_check)(gtk2_widget->style, gtk2_black_pixmap, state_type,1848shadow_type, NULL, gtk2_widget, detail,1849x, y, width, height);1850}18511852static void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,1853GtkShadowType shadow_type, const gchar *detail,1854gint x, gint y, gint width, gint height)1855{1856gtk2_widget = gtk2_get_widget(widget_type);1857(*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_white_pixmap, state_type,1858shadow_type, NULL, gtk2_widget, detail,1859x, y, width, height);1860(*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_black_pixmap, state_type,1861shadow_type, NULL, gtk2_widget, detail,1862x, y, width, height);1863}18641865static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,1866const gchar *detail, gint x, gint y, gint width, gint height,1867GtkExpanderStyle expander_style)1868{1869gtk2_widget = gtk2_get_widget(widget_type);1870(*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_white_pixmap,1871state_type, NULL, gtk2_widget, detail,1872x + width / 2, y + height / 2, expander_style);1873(*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_black_pixmap,1874state_type, NULL, gtk2_widget, detail,1875x + width / 2, y + height / 2, expander_style);1876}18771878static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,1879GtkShadowType shadow_type, const gchar *detail,1880gint x, gint y, gint width, gint height, GtkPositionType gap_side)1881{1882gtk2_widget = gtk2_get_widget(widget_type);1883(*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_white_pixmap,1884state_type, shadow_type, NULL, gtk2_widget, detail,1885x, y, width, height, gap_side);1886(*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_black_pixmap,1887state_type, shadow_type, NULL, gtk2_widget, detail,1888x, y, width, height, gap_side);1889}18901891static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,1892GtkShadowType shadow_type, const gchar *detail,1893gint x, gint y, gint width, gint height, gboolean has_focus)1894{1895gtk2_widget = gtk2_get_widget(widget_type);18961897if (has_focus)1898((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;1899else1900((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;19011902(*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_white_pixmap,1903state_type, shadow_type, NULL, gtk2_widget, detail,1904x, y, width, height);1905(*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_black_pixmap,1906state_type, shadow_type, NULL, gtk2_widget, detail,1907x, y, width, height);1908}19091910static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,1911const char *detail, gint x, gint y, gint width, gint height)1912{1913gtk2_widget = gtk2_get_widget(widget_type);1914(*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_white_pixmap, state_type,1915NULL, gtk2_widget, detail, x, y, width, height);1916(*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_black_pixmap, state_type,1917NULL, gtk2_widget, detail, x, y, width, height);1918}19191920static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,1921GtkShadowType shadow_type, const gchar *detail,1922gint x, gint y, gint width, gint height, GtkOrientation orientation)1923{1924gtk2_widget = gtk2_get_widget(widget_type);1925(*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_white_pixmap, state_type,1926shadow_type, NULL, gtk2_widget, detail,1927x, y, width, height, orientation);1928(*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_black_pixmap, state_type,1929shadow_type, NULL, gtk2_widget, detail,1930x, y, width, height, orientation);1931}19321933static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,1934const gchar *detail, gint x, gint y, gint width, gint height)1935{1936gtk2_widget = gtk2_get_widget(widget_type);1937(*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_white_pixmap, state_type,1938NULL, gtk2_widget, detail, x, x + width, y);1939(*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_black_pixmap, state_type,1940NULL, gtk2_widget, detail, x, x + width, y);1941}19421943static void gtk2_paint_option(WidgetType widget_type, gint synth_state,1944const gchar *detail, gint x, gint y, gint width, gint height)1945{1946GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);1947GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);19481949gtk2_widget = gtk2_get_widget(widget_type);1950init_toggle_widget(widget_type, synth_state);19511952(*fp_gtk_paint_option)(gtk2_widget->style, gtk2_white_pixmap, state_type,1953shadow_type, NULL, gtk2_widget, detail,1954x, y, width, height);1955(*fp_gtk_paint_option)(gtk2_widget->style, gtk2_black_pixmap, state_type,1956shadow_type, NULL, gtk2_widget, detail,1957x, y, width, height);1958}19591960static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,1961GtkShadowType shadow_type, const gchar *detail,1962gint x, gint y, gint width, gint height,1963gint synth_state, GtkTextDirection dir)1964{1965gtk2_widget = gtk2_get_widget(widget_type);19661967/*1968* The clearlooks engine sometimes looks at the widget's state field1969* instead of just the state_type variable that we pass in, so to account1970* for those cases we set the widget's state field accordingly. The1971* flags field is similarly important for things like focus state.1972*/1973gtk2_widget->state = state_type;19741975/*1976* Some engines (e.g. clearlooks) will paint the shadow of certain1977* widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the1978* the text direction.1979*/1980gtk2_set_direction(gtk2_widget, dir);19811982switch (widget_type) {1983case COMBO_BOX_TEXT_FIELD:1984case FORMATTED_TEXT_FIELD:1985case PASSWORD_FIELD:1986case SPINNER_TEXT_FIELD:1987case TEXT_FIELD:1988if (synth_state & FOCUSED) {1989((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;1990} else {1991((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;1992}1993break;1994default:1995break;1996}19971998(*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_white_pixmap, state_type,1999shadow_type, NULL, gtk2_widget, detail, x, y, width, height);2000(*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_black_pixmap, state_type,2001shadow_type, NULL, gtk2_widget, detail, x, y, width, height);20022003/*2004* Reset the text direction to the default value so that we don't2005* accidentally affect other operations and widgets.2006*/2007gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);2008}20092010static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,2011GtkShadowType shadow_type, const gchar *detail,2012gint x, gint y, gint width, gint height, GtkOrientation orientation,2013gboolean has_focus)2014{2015gtk2_widget = gtk2_get_widget(widget_type);2016(*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type,2017shadow_type, NULL, gtk2_widget, detail,2018x, y, width, height, orientation);2019(*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_black_pixmap, state_type,2020shadow_type, NULL, gtk2_widget, detail,2021x, y, width, height, orientation);2022}20232024static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,2025const gchar *detail, gint x, gint y, gint width, gint height)2026{2027gtk2_widget = gtk2_get_widget(widget_type);2028(*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_white_pixmap, state_type,2029NULL, gtk2_widget, detail, y, y + height, x);2030(*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_black_pixmap, state_type,2031NULL, gtk2_widget, detail, y, y + height, x);2032}20332034static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,2035gint x, gint y, gint width, gint height)2036{2037gtk2_widget = gtk2_get_widget(widget_type);2038(*fp_gtk_style_apply_default_background)(gtk2_widget->style,2039gtk2_white_pixmap, TRUE, state_type, NULL, x, y, width, height);2040(*fp_gtk_style_apply_default_background)(gtk2_widget->style,2041gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height);2042}20432044static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,2045GtkIconSize size, GtkTextDirection direction, const char *detail)2046{2047init_containers();2048gtk2_widget = gtk2_get_widget((widget_type < 0) ? IMAGE : widget_type);2049gtk2_widget->state = GTK_STATE_NORMAL;2050(*fp_gtk_widget_set_direction)(gtk2_widget, direction);2051return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail);2052}20532054static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf,2055jmethodID icon_upcall_method, jobject this) {2056if (!pixbuf) {2057return JNI_FALSE;2058}2059guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);2060if (pixbuf_data) {2061int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);2062int width = (*fp_gdk_pixbuf_get_width)(pixbuf);2063int height = (*fp_gdk_pixbuf_get_height)(pixbuf);2064int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);2065int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);2066gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);20672068jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));2069JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);20702071(*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),2072(jbyte *)pixbuf_data);2073(*fp_g_object_unref)(pixbuf);20742075/* Call the callback method to create the image on the Java side. */2076(*env)->CallVoidMethod(env, this, icon_upcall_method, data,2077width, height, row_stride, bps, channels, alpha);2078return JNI_TRUE;2079}2080return JNI_FALSE;2081}20822083static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename,2084GError **error, jmethodID icon_upcall_method, jobject this) {2085GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error);2086return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);2087}20882089static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type,2090const gchar *stock_id, GtkIconSize size,2091GtkTextDirection direction, const char *detail,2092jmethodID icon_upcall_method, jobject this) {2093GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size,2094direction, detail);2095return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);2096}20972098/*************************************************/2099static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type)2100{2101init_containers();21022103gtk2_widget = gtk2_get_widget(widget_type);2104GtkStyle* style = gtk2_widget->style;2105return style->xthickness;2106}21072108static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type)2109{2110init_containers();21112112gtk2_widget = gtk2_get_widget(widget_type);2113GtkStyle* style = gtk2_widget->style;2114return style->ythickness;2115}21162117/*************************************************/2118static guint8 recode_color(guint16 channel)2119{2120return (guint8)(channel>>8);2121}21222123static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,2124GtkStateType state_type, ColorType color_type)2125{2126gint result = 0;2127GdkColor *color = NULL;21282129init_containers();21302131gtk2_widget = gtk2_get_widget(widget_type);2132GtkStyle* style = gtk2_widget->style;21332134switch (color_type)2135{2136case FOREGROUND:2137color = &(style->fg[state_type]);2138break;2139case BACKGROUND:2140color = &(style->bg[state_type]);2141break;2142case TEXT_FOREGROUND:2143color = &(style->text[state_type]);2144break;2145case TEXT_BACKGROUND:2146color = &(style->base[state_type]);2147break;2148case LIGHT:2149color = &(style->light[state_type]);2150break;2151case DARK:2152color = &(style->dark[state_type]);2153break;2154case MID:2155color = &(style->mid[state_type]);2156break;2157case FOCUS:2158case BLACK:2159color = &(style->black);2160break;2161case WHITE:2162color = &(style->white);2163break;2164}21652166if (color)2167result = recode_color(color->red) << 16 |2168recode_color(color->green) << 8 |2169recode_color(color->blue);21702171return result;2172}21732174/*************************************************/2175static jobject create_Boolean(JNIEnv *env, jboolean boolean_value);2176static jobject create_Integer(JNIEnv *env, jint int_value);2177static jobject create_Long(JNIEnv *env, jlong long_value);2178static jobject create_Float(JNIEnv *env, jfloat float_value);2179static jobject create_Double(JNIEnv *env, jdouble double_value);2180static jobject create_Character(JNIEnv *env, jchar char_value);2181static jobject create_Insets(JNIEnv *env, GtkBorder *border);21822183static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type,2184const char* key)2185{2186init_containers();21872188gtk2_widget = gtk2_get_widget(widget_type);21892190GValue value;2191value.g_type = 0;21922193GParamSpec* param = (*fp_gtk_widget_class_find_style_property)(2194((GTypeInstance*)gtk2_widget)->g_class, key);2195if( param )2196{2197(*fp_g_value_init)( &value, param->value_type );2198(*fp_gtk_widget_style_get_property)(gtk2_widget, key, &value);21992200if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN ))2201{2202gboolean val = (*fp_g_value_get_boolean)(&value);2203return create_Boolean(env, (jboolean)val);2204}2205else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR ))2206{2207gchar val = (*fp_g_value_get_char)(&value);2208return create_Character(env, (jchar)val);2209}2210else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR ))2211{2212guchar val = (*fp_g_value_get_uchar)(&value);2213return create_Character(env, (jchar)val);2214}2215else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT ))2216{2217gint val = (*fp_g_value_get_int)(&value);2218return create_Integer(env, (jint)val);2219}2220else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT ))2221{2222guint val = (*fp_g_value_get_uint)(&value);2223return create_Integer(env, (jint)val);2224}2225else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_LONG ))2226{2227glong val = (*fp_g_value_get_long)(&value);2228return create_Long(env, (jlong)val);2229}2230else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG ))2231{2232gulong val = (*fp_g_value_get_ulong)(&value);2233return create_Long(env, (jlong)val);2234}2235else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 ))2236{2237gint64 val = (*fp_g_value_get_int64)(&value);2238return create_Long(env, (jlong)val);2239}2240else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 ))2241{2242guint64 val = (*fp_g_value_get_uint64)(&value);2243return create_Long(env, (jlong)val);2244}2245else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT ))2246{2247gfloat val = (*fp_g_value_get_float)(&value);2248return create_Float(env, (jfloat)val);2249}2250else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE ))2251{2252gdouble val = (*fp_g_value_get_double)(&value);2253return create_Double(env, (jdouble)val);2254}2255else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM ))2256{2257gint val = (*fp_g_value_get_enum)(&value);2258return create_Integer(env, (jint)val);2259}2260else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS ))2261{2262guint val = (*fp_g_value_get_flags)(&value);2263return create_Integer(env, (jint)val);2264}2265else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_STRING ))2266{2267const gchar* val = (*fp_g_value_get_string)(&value);22682269/* We suppose that all values come in C locale and2270* utf-8 representation of a string is the same as2271* the string itself. If this isn't so we should2272* use g_convert.2273*/2274return (*env)->NewStringUTF(env, val);2275}2276else if( (*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER ))2277{2278GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value);2279return border ? create_Insets(env, border) : NULL;2280}22812282/* TODO: Other types are not supported yet.*/2283/* else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM ))2284{2285GParamSpec* val = (*fp_g_value_get_param)(&value);2286printf( "Param: %p\n", val );2287}2288else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED ))2289{2290gpointer* val = (*fp_g_value_get_boxed)(&value);2291printf( "Boxed: %p\n", val );2292}2293else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER ))2294{2295gpointer* val = (*fp_g_value_get_pointer)(&value);2296printf( "Pointer: %p\n", val );2297}2298else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT ))2299{2300GObject* val = (GObject*)(*fp_g_value_get_object)(&value);2301printf( "Object: %p\n", val );2302}*/2303}23042305return NULL;2306}23072308static void gtk2_set_range_value(WidgetType widget_type, jdouble value,2309jdouble min, jdouble max, jdouble visible)2310{2311GtkAdjustment *adj;23122313gtk2_widget = gtk2_get_widget(widget_type);23142315adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk2_widget);2316adj->value = (gdouble)value;2317adj->lower = (gdouble)min;2318adj->upper = (gdouble)max;2319adj->page_size = (gdouble)visible;2320}23212322/*************************************************/2323static jobject create_Object(JNIEnv *env, jmethodID *cid,2324const char* class_name,2325const char* signature,2326jvalue* value)2327{2328jclass class;2329jobject result;23302331class = (*env)->FindClass(env, class_name);2332if( class == NULL )2333return NULL; /* can't find/load the class, exception thrown */23342335if( *cid == NULL)2336{2337*cid = (*env)->GetMethodID(env, class, "<init>", signature);2338if( *cid == NULL )2339{2340(*env)->DeleteLocalRef(env, class);2341return NULL; /* can't find/get the method, exception thrown */2342}2343}23442345result = (*env)->NewObjectA(env, class, *cid, value);23462347(*env)->DeleteLocalRef(env, class);2348return result;2349}23502351jobject create_Boolean(JNIEnv *env, jboolean boolean_value)2352{2353static jmethodID cid = NULL;2354jvalue value;23552356value.z = boolean_value;23572358return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value);2359}23602361jobject create_Integer(JNIEnv *env, jint int_value)2362{2363static jmethodID cid = NULL;2364jvalue value;23652366value.i = int_value;23672368return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value);2369}23702371jobject create_Long(JNIEnv *env, jlong long_value)2372{2373static jmethodID cid = NULL;2374jvalue value;23752376value.j = long_value;23772378return create_Object(env, &cid, "java/lang/Long", "(J)V", &value);2379}23802381jobject create_Float(JNIEnv *env, jfloat float_value)2382{2383static jmethodID cid = NULL;2384jvalue value;23852386value.f = float_value;23872388return create_Object(env, &cid, "java/lang/Float", "(F)V", &value);2389}23902391jobject create_Double(JNIEnv *env, jdouble double_value)2392{2393static jmethodID cid = NULL;2394jvalue value;23952396value.d = double_value;23972398return create_Object(env, &cid, "java/lang/Double", "(D)V", &value);2399}24002401jobject create_Character(JNIEnv *env, jchar char_value)2402{2403static jmethodID cid = NULL;2404jvalue value;24052406value.c = char_value;24072408return create_Object(env, &cid, "java/lang/Character", "(C)V", &value);2409}241024112412jobject create_Insets(JNIEnv *env, GtkBorder *border)2413{2414static jmethodID cid = NULL;2415jvalue values[4];24162417values[0].i = border->top;2418values[1].i = border->left;2419values[2].i = border->bottom;2420values[3].i = border->right;24212422return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values);2423}24242425/*********************************************/2426static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type)2427{2428init_containers();24292430gtk2_widget = gtk2_get_widget(widget_type);2431jstring result = NULL;2432GtkStyle* style = gtk2_widget->style;24332434if (style && style->font_desc)2435{2436gchar* val = (*fp_pango_font_description_to_string)(style->font_desc);2437result = (*env)->NewStringUTF(env, val);2438(*fp_g_free)( val );2439}24402441return result;2442}24432444/***********************************************/2445static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key)2446{2447jobject result = NULL;2448gchar* strval = NULL;24492450(*fp_g_object_get)(settings, key, &strval, NULL);2451result = (*env)->NewStringUTF(env, strval);2452(*fp_g_free)(strval);24532454return result;2455}24562457static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)2458{2459gint intval = 0;2460(*fp_g_object_get)(settings, key, &intval, NULL);2461return create_Integer(env, intval);2462}24632464static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key)2465{2466gint intval = 0;2467(*fp_g_object_get)(settings, key, &intval, NULL);2468return create_Boolean(env, intval);2469}24702471static jobject gtk2_get_setting(JNIEnv *env, Setting property)2472{2473GtkSettings* settings = (*fp_gtk_settings_get_default)();24742475switch (property)2476{2477case GTK_FONT_NAME:2478return get_string_property(env, settings, "gtk-font-name");2479case GTK_ICON_SIZES:2480return get_string_property(env, settings, "gtk-icon-sizes");2481case GTK_CURSOR_BLINK:2482return get_boolean_property(env, settings, "gtk-cursor-blink");2483case GTK_CURSOR_BLINK_TIME:2484return get_integer_property(env, settings, "gtk-cursor-blink-time");2485}24862487return NULL;2488}24892490static gboolean gtk2_get_drawable_data(JNIEnv *env, jintArray pixelArray, jint x,2491jint y, jint width, jint height, jint jwidth, int dx, int dy, jint scale) {2492GdkPixbuf *pixbuf;2493jint *ary;24942495GdkWindow *root = (*fp_gdk_get_default_root_window)();24962497pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, x, y,24980, 0, width, height);2499if (pixbuf && scale != 1) {2500GdkPixbuf *scaledPixbuf;2501x /= scale;2502y /= scale;2503width /= scale;2504height /= scale;2505dx /= scale;2506dy /= scale;2507scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,2508GDK_INTERP_BILINEAR);2509(*fp_g_object_unref)(pixbuf);2510pixbuf = scaledPixbuf;2511}25122513if (pixbuf) {2514int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);2515int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);25162517if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width2518&& (*fp_gdk_pixbuf_get_height)(pixbuf) == height2519&& (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 82520&& (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB2521&& nchan >= 32522) {2523guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);25242525ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);2526if (ary) {2527jint _x, _y;2528int index;2529for (_y = 0; _y < height; _y++) {2530for (_x = 0; _x < width; _x++) {2531p = pix + (intptr_t) _y * stride + _x * nchan;25322533index = (_y + dy) * jwidth + (_x + dx);2534ary[index] = 0xff0000002535| (p[0] << 16)2536| (p[1] << 8)2537| (p[2]);25382539}2540}2541(*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);2542}2543}2544(*fp_g_object_unref)(pixbuf);2545}2546return JNI_FALSE;2547}25482549static GdkWindow* gtk2_get_window(void *widget) {2550return ((GtkWidget*)widget)->window;2551}25522553void gtk2_init(GtkApi* gtk) {2554gtk->version = GTK_2;25552556gtk->show_uri_load = >k2_show_uri_load;2557gtk->unload = >k2_unload;2558gtk->flush_event_loop = &flush_gtk_event_loop;2559gtk->gtk_check_version = fp_gtk_check_version;2560gtk->get_setting = >k2_get_setting;25612562gtk->paint_arrow = >k2_paint_arrow;2563gtk->paint_box = >k2_paint_box;2564gtk->paint_box_gap = >k2_paint_box_gap;2565gtk->paint_expander = >k2_paint_expander;2566gtk->paint_extension = >k2_paint_extension;2567gtk->paint_flat_box = >k2_paint_flat_box;2568gtk->paint_focus = >k2_paint_focus;2569gtk->paint_handle = >k2_paint_handle;2570gtk->paint_hline = >k2_paint_hline;2571gtk->paint_vline = >k2_paint_vline;2572gtk->paint_option = >k2_paint_option;2573gtk->paint_shadow = >k2_paint_shadow;2574gtk->paint_slider = >k2_paint_slider;2575gtk->paint_background = >k_paint_background;2576gtk->paint_check = >k2_paint_check;2577gtk->set_range_value = >k2_set_range_value;25782579gtk->init_painting = >k2_init_painting;2580gtk->copy_image = >k2_copy_image;25812582gtk->get_xthickness = >k2_get_xthickness;2583gtk->get_ythickness = >k2_get_ythickness;2584gtk->get_color_for_state = >k2_get_color_for_state;2585gtk->get_class_value = >k2_get_class_value;25862587gtk->get_pango_font_name = >k2_get_pango_font_name;2588gtk->get_icon_data = >k2_get_icon_data;2589gtk->get_file_icon_data = >k2_get_file_icon_data;2590gtk->gdk_threads_enter = fp_gdk_threads_enter;2591gtk->gdk_threads_leave = fp_gdk_threads_leave;2592gtk->gtk_show_uri = fp_gtk_show_uri;2593gtk->get_drawable_data = >k2_get_drawable_data;2594gtk->g_free = fp_g_free;25952596gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename;2597gtk->gtk_widget_hide = fp_gtk_widget_hide;2598gtk->gtk_main_quit = fp_gtk_main_quit;2599gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new;2600gtk->gtk_file_chooser_set_current_folder =2601fp_gtk_file_chooser_set_current_folder;2602gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename;2603gtk->gtk_file_chooser_set_current_name =2604fp_gtk_file_chooser_set_current_name;2605gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom;2606gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter;2607gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type;2608gtk->gtk_file_filter_new = fp_gtk_file_filter_new;2609gtk->gtk_file_chooser_set_do_overwrite_confirmation =2610fp_gtk_file_chooser_set_do_overwrite_confirmation;2611gtk->gtk_file_chooser_set_select_multiple =2612fp_gtk_file_chooser_set_select_multiple;2613gtk->gtk_file_chooser_get_current_folder =2614fp_gtk_file_chooser_get_current_folder;2615gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames;2616gtk->gtk_g_slist_length = fp_gtk_g_slist_length;2617gtk->g_signal_connect_data = fp_g_signal_connect_data;2618gtk->gtk_widget_show = fp_gtk_widget_show;2619gtk->gtk_main = fp_gtk_main;2620gtk->gtk_main_level = fp_gtk_main_level;2621gtk->g_path_get_dirname = fp_g_path_get_dirname;2622gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid;2623gtk->gtk_widget_destroy = fp_gtk_widget_destroy;2624gtk->gtk_window_present = fp_gtk_window_present;2625gtk->gtk_window_move = fp_gtk_window_move;2626gtk->gtk_window_resize = fp_gtk_window_resize;2627gtk->get_window = >k2_get_window;26282629gtk->g_object_unref = fp_g_object_unref;2630gtk->g_list_append = fp_g_list_append;2631gtk->g_list_free = fp_g_list_free;2632gtk->g_list_free_full = fp_g_list_free_full;2633}263426352636