Path: blob/master/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c
66646 views
/*1* Copyright (c) 2005, 2021, 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_box)(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_flat_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_check)(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_option)(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_box_gap)(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,169GtkPositionType gap_side, gint gap_x, gint gap_width);170static void (*fp_gtk_paint_extension)(GtkStyle* style, GdkWindow* window,171GtkStateType state_type, GtkShadowType shadow_type,172GdkRectangle* area, GtkWidget* widget, const gchar* detail,173gint x, gint y, gint width, gint height, GtkPositionType gap_side);174static void (*fp_gtk_paint_focus)(GtkStyle* style, GdkWindow* window,175GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,176const gchar* detail, gint x, gint y, gint width, gint height);177static void (*fp_gtk_paint_slider)(GtkStyle* style, GdkWindow* window,178GtkStateType state_type, GtkShadowType shadow_type,179GdkRectangle* area, GtkWidget* widget, const gchar* detail,180gint x, gint y, gint width, gint height, GtkOrientation orientation);181static void (*fp_gtk_paint_handle)(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_expander)(GtkStyle* style, GdkWindow* window,186GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,187const gchar* detail, gint x, gint y, GtkExpanderStyle expander_style);188static void (*fp_gtk_style_apply_default_background)(GtkStyle* style,189GdkWindow* window, gboolean set_bg, GtkStateType state_type,190GdkRectangle* area, gint x, gint y, gint width, gint height);191192/* Widget creation */193static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type,194GtkShadowType shadow_type);195static GtkWidget* (*fp_gtk_button_new)();196static GtkWidget* (*fp_gtk_check_button_new)();197static GtkWidget* (*fp_gtk_check_menu_item_new)();198static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title);199static GtkWidget* (*fp_gtk_combo_box_new)();200static GtkWidget* (*fp_gtk_combo_box_entry_new)();201static GtkWidget* (*fp_gtk_entry_new)();202static GtkWidget* (*fp_gtk_fixed_new)();203static GtkWidget* (*fp_gtk_handle_box_new)();204static GtkWidget* (*fp_gtk_hpaned_new)();205static GtkWidget* (*fp_gtk_vpaned_new)();206static GtkWidget* (*fp_gtk_hscale_new)(GtkAdjustment* adjustment);207static GtkWidget* (*fp_gtk_vscale_new)(GtkAdjustment* adjustment);208static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment);209static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment);210static GtkWidget* (*fp_gtk_hseparator_new)();211static GtkWidget* (*fp_gtk_vseparator_new)();212static GtkWidget* (*fp_gtk_image_new)();213static GtkWidget* (*fp_gtk_label_new)(const gchar* str);214static GtkWidget* (*fp_gtk_menu_new)();215static GtkWidget* (*fp_gtk_menu_bar_new)();216static GtkWidget* (*fp_gtk_menu_item_new)();217static GtkWidget* (*fp_gtk_notebook_new)();218static GtkWidget* (*fp_gtk_progress_bar_new)();219static GtkWidget* (*fp_gtk_progress_bar_set_orientation)(220GtkProgressBar *pbar,221GtkProgressBarOrientation orientation);222static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group);223static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group);224static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment,225GtkAdjustment *vadjustment);226static GtkWidget* (*fp_gtk_separator_menu_item_new)();227static GtkWidget* (*fp_gtk_separator_tool_item_new)();228static GtkWidget* (*fp_gtk_text_view_new)();229static GtkWidget* (*fp_gtk_toggle_button_new)();230static GtkWidget* (*fp_gtk_toolbar_new)();231static GtkWidget* (*fp_gtk_tree_view_new)();232static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment,233GtkAdjustment *vadjustment);234static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type);235static GtkWidget* (*fp_gtk_dialog_new)();236static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment,237gdouble climb_rate, guint digits);238static GtkWidget* (*fp_gtk_frame_new)(const gchar *label);239240/* Other widget operations */241static GtkObject* (*fp_gtk_adjustment_new)(gdouble value,242gdouble lower, gdouble upper, gdouble step_increment,243gdouble page_increment, gdouble page_size);244static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget);245static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell,246GtkWidget *child);247static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item,248GtkWidget *submenu);249static void (*fp_gtk_widget_realize)(GtkWidget *widget);250static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget,251const gchar *stock_id, GtkIconSize size, const gchar *detail);252static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name);253static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent);254static void (*fp_gtk_widget_set_direction)(GtkWidget *widget,255GtkTextDirection direction);256static void (*fp_gtk_widget_style_get)(GtkWidget *widget,257const gchar *first_property_name, ...);258static void (*fp_gtk_widget_class_install_style_property)(259GtkWidgetClass* class, GParamSpec *pspec);260static GParamSpec* (*fp_gtk_widget_class_find_style_property)(261GtkWidgetClass* class, const gchar* property_name);262static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget,263const gchar* property_name, GValue* value);264static char* (*fp_pango_font_description_to_string)(265const PangoFontDescription* fd);266static GtkSettings* (*fp_gtk_settings_get_default)();267static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget);268static GType (*fp_gtk_border_get_type)();269static void (*fp_gtk_arrow_set)(GtkWidget* arrow,270GtkArrowType arrow_type,271GtkShadowType shadow_type);272static void (*fp_gtk_widget_size_request)(GtkWidget *widget,273GtkRequisition *requisition);274static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range);275276/* Method bodies */277278static void throw_exception(JNIEnv *env, const char* name, const char* message)279{280jclass class = (*env)->FindClass(env, name);281282if (class != NULL)283(*env)->ThrowNew(env, class, message);284285(*env)->DeleteLocalRef(env, class);286}287288/* This is a workaround for the bug:289* http://sourceware.org/bugzilla/show_bug.cgi?id=1814290* (dlsym/dlopen clears dlerror state)291* This bug is specific to Linux, but there is no harm in292* applying this workaround on Solaris as well.293*/294static void* dl_symbol(const char* name)295{296void* result = dlsym(gtk2_libhandle, name);297if (!result)298longjmp(j, NO_SYMBOL_EXCEPTION);299300return result;301}302303static void* dl_symbol_gthread(const char* name)304{305void* result = dlsym(gthread_libhandle, name);306if (!result)307longjmp(j, NO_SYMBOL_EXCEPTION);308309return result;310}311312gboolean gtk2_check(const char* lib_name, gboolean load)313{314if (gtk2_libhandle != NULL) {315/* We've already successfully opened the GTK libs, so return true. */316return TRUE;317} else {318void *lib = NULL;319320#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);335if (lib == NULL) {336return FALSE;337}338339fp_gtk_check_version = dlsym(lib, "gtk_check_version");340/* Check for GTK 2.2+ */341if (!fp_gtk_check_version(2, 2, 0)) {342return TRUE;343}344345// 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065346// dlclose(lib);347348return FALSE;349}350}351352#define ADD_SUPPORTED_ACTION(actionStr) \353do { \354jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, "Ljava/awt/Desktop$Action;"); \355if (!(*env)->ExceptionCheck(env)) { \356jobject action = (*env)->GetStaticObjectField(env, cls_action, fld_action); \357(*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, action); \358} else { \359(*env)->ExceptionClear(env); \360} \361} while(0);362363364static void update_supported_actions(JNIEnv *env) {365GVfs * (*fp_g_vfs_get_default) (void);366const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);367const gchar * const * schemes = NULL;368369jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action");370CHECK_NULL(cls_action);371jclass cls_xDesktopPeer = (*env)->FindClass(env, "sun/awt/X11/XDesktopPeer");372CHECK_NULL(cls_xDesktopPeer);373jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, cls_xDesktopPeer, "supportedActions", "Ljava/util/List;");374CHECK_NULL(fld_supportedActions);375jobject supportedActions = (*env)->GetStaticObjectField(env, cls_xDesktopPeer, fld_supportedActions);376377jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList");378CHECK_NULL(cls_arrayList);379jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", "(Ljava/lang/Object;)Z");380CHECK_NULL(mid_arrayListAdd);381jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, "clear", "()V");382CHECK_NULL(mid_arrayListClear);383384(*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear);385386ADD_SUPPORTED_ACTION("OPEN");387388/**389* gtk_show_uri() documentation says:390*391* > you need to install gvfs to get support for uri schemes such as http://392* > or ftp://, as only local files are handled by GIO itself.393*394* So OPEN action was safely added here.395* However, it looks like Solaris 11 have gvfs support only for 32-bit396* applications only by default.397*/398399fp_g_vfs_get_default = dl_symbol("g_vfs_get_default");400fp_g_vfs_get_supported_uri_schemes = dl_symbol("g_vfs_get_supported_uri_schemes");401dlerror();402403if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) {404GVfs * vfs = fp_g_vfs_get_default();405schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL;406if (schemes) {407int i = 0;408while (schemes[i]) {409if (strcmp(schemes[i], "http") == 0) {410ADD_SUPPORTED_ACTION("BROWSE");411ADD_SUPPORTED_ACTION("MAIL");412break;413}414i++;415}416}417} else {418#ifdef DEBUG419fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n");420#endif /* DEBUG */421}422423}424/**425* Functions for awt_Desktop.c426*/427static gboolean gtk2_show_uri_load(JNIEnv *env) {428gboolean success = FALSE;429dlerror();430const char *gtk_version = fp_gtk_check_version(2, 14, 0);431if (gtk_version != NULL) {432// The gtk_show_uri is available from GTK+ 2.14433#ifdef DEBUG434fprintf (stderr, "The version of GTK is %s. "435"The gtk_show_uri function is supported "436"since GTK+ 2.14.\n", gtk_version);437#endif /* DEBUG */438} else {439// Loading symbols only if the GTK version is 2.14 and higher440fp_gtk_show_uri = dl_symbol("gtk_show_uri");441const char *dlsym_error = dlerror();442if (dlsym_error) {443#ifdef DEBUG444fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error);445#endif /* DEBUG */446} else if (fp_gtk_show_uri == NULL) {447#ifdef DEBUG448fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");449#endif /* DEBUG */450} else {451gtk->gtk_show_uri = fp_gtk_show_uri;452update_supported_actions(env);453success = TRUE;454}455}456return success;457}458459/**460* Functions for sun_awt_X11_GtkFileDialogPeer.c461*/462static void gtk2_file_chooser_load()463{464fp_gtk_file_chooser_get_filename = dl_symbol(465"gtk_file_chooser_get_filename");466fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new");467fp_gtk_file_chooser_set_current_folder = dl_symbol(468"gtk_file_chooser_set_current_folder");469fp_gtk_file_chooser_set_filename = dl_symbol(470"gtk_file_chooser_set_filename");471fp_gtk_file_chooser_set_current_name = dl_symbol(472"gtk_file_chooser_set_current_name");473fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom");474fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");475fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");476fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");477if (fp_gtk_check_version(2, 8, 0) == NULL) {478fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(479"gtk_file_chooser_set_do_overwrite_confirmation");480}481fp_gtk_file_chooser_set_select_multiple = dl_symbol(482"gtk_file_chooser_set_select_multiple");483fp_gtk_file_chooser_get_current_folder = dl_symbol(484"gtk_file_chooser_get_current_folder");485fp_gtk_file_chooser_get_filenames = dl_symbol(486"gtk_file_chooser_get_filenames");487fp_gtk_g_slist_length = dl_symbol("g_slist_length");488fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid");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_get_default_root_window =557dl_symbol("gdk_get_default_root_window");558fp_gdk_pixmap_new = dl_symbol("gdk_pixmap_new");559fp_gdk_pixbuf_get_from_drawable =560dl_symbol("gdk_pixbuf_get_from_drawable");561fp_gdk_pixbuf_scale_simple =562dl_symbol("gdk_pixbuf_scale_simple");563fp_gdk_gc_new = dl_symbol("gdk_gc_new");564fp_gdk_rgb_gc_set_foreground =565dl_symbol("gdk_rgb_gc_set_foreground");566fp_gdk_draw_rectangle = dl_symbol("gdk_draw_rectangle");567fp_gdk_drawable_get_size = dl_symbol("gdk_drawable_get_size");568569/* Pixbuf */570fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new");571fp_gdk_pixbuf_new_from_file =572dl_symbol("gdk_pixbuf_new_from_file");573fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width");574fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height");575fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels");576fp_gdk_pixbuf_get_rowstride =577dl_symbol("gdk_pixbuf_get_rowstride");578fp_gdk_pixbuf_get_has_alpha =579dl_symbol("gdk_pixbuf_get_has_alpha");580fp_gdk_pixbuf_get_bits_per_sample =581dl_symbol("gdk_pixbuf_get_bits_per_sample");582fp_gdk_pixbuf_get_n_channels =583dl_symbol("gdk_pixbuf_get_n_channels");584fp_gdk_pixbuf_get_colorspace =585dl_symbol("gdk_pixbuf_get_colorspace");586587/* GTK painting */588fp_gtk_init_check = dl_symbol("gtk_init_check");589fp_gtk_paint_hline = dl_symbol("gtk_paint_hline");590fp_gtk_paint_vline = dl_symbol("gtk_paint_vline");591fp_gtk_paint_shadow = dl_symbol("gtk_paint_shadow");592fp_gtk_paint_arrow = dl_symbol("gtk_paint_arrow");593fp_gtk_paint_box = dl_symbol("gtk_paint_box");594fp_gtk_paint_flat_box = dl_symbol("gtk_paint_flat_box");595fp_gtk_paint_check = dl_symbol("gtk_paint_check");596fp_gtk_paint_option = dl_symbol("gtk_paint_option");597fp_gtk_paint_box_gap = dl_symbol("gtk_paint_box_gap");598fp_gtk_paint_extension = dl_symbol("gtk_paint_extension");599fp_gtk_paint_focus = dl_symbol("gtk_paint_focus");600fp_gtk_paint_slider = dl_symbol("gtk_paint_slider");601fp_gtk_paint_handle = dl_symbol("gtk_paint_handle");602fp_gtk_paint_expander = dl_symbol("gtk_paint_expander");603fp_gtk_style_apply_default_background =604dl_symbol("gtk_style_apply_default_background");605606/* GTK widgets */607fp_gtk_arrow_new = dl_symbol("gtk_arrow_new");608fp_gtk_button_new = dl_symbol("gtk_button_new");609fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new");610fp_gtk_check_button_new = dl_symbol("gtk_check_button_new");611fp_gtk_check_menu_item_new =612dl_symbol("gtk_check_menu_item_new");613fp_gtk_color_selection_dialog_new =614dl_symbol("gtk_color_selection_dialog_new");615fp_gtk_entry_new = dl_symbol("gtk_entry_new");616fp_gtk_fixed_new = dl_symbol("gtk_fixed_new");617fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new");618fp_gtk_image_new = dl_symbol("gtk_image_new");619fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new");620fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new");621fp_gtk_hscale_new = dl_symbol("gtk_hscale_new");622fp_gtk_vscale_new = dl_symbol("gtk_vscale_new");623fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new");624fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new");625fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new");626fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new");627fp_gtk_label_new = dl_symbol("gtk_label_new");628fp_gtk_menu_new = dl_symbol("gtk_menu_new");629fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new");630fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new");631fp_gtk_menu_item_set_submenu =632dl_symbol("gtk_menu_item_set_submenu");633fp_gtk_notebook_new = dl_symbol("gtk_notebook_new");634fp_gtk_progress_bar_new =635dl_symbol("gtk_progress_bar_new");636fp_gtk_progress_bar_set_orientation =637dl_symbol("gtk_progress_bar_set_orientation");638fp_gtk_radio_button_new =639dl_symbol("gtk_radio_button_new");640fp_gtk_radio_menu_item_new =641dl_symbol("gtk_radio_menu_item_new");642fp_gtk_scrolled_window_new =643dl_symbol("gtk_scrolled_window_new");644fp_gtk_separator_menu_item_new =645dl_symbol("gtk_separator_menu_item_new");646fp_gtk_text_view_new = dl_symbol("gtk_text_view_new");647fp_gtk_toggle_button_new =648dl_symbol("gtk_toggle_button_new");649fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new");650fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new");651fp_gtk_viewport_new = dl_symbol("gtk_viewport_new");652fp_gtk_window_new = dl_symbol("gtk_window_new");653fp_gtk_window_present = dl_symbol("gtk_window_present");654fp_gtk_window_move = dl_symbol("gtk_window_move");655fp_gtk_window_resize = dl_symbol("gtk_window_resize");656657fp_gtk_dialog_new = dl_symbol("gtk_dialog_new");658fp_gtk_frame_new = dl_symbol("gtk_frame_new");659660fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new");661fp_gtk_container_add = dl_symbol("gtk_container_add");662fp_gtk_menu_shell_append =663dl_symbol("gtk_menu_shell_append");664fp_gtk_widget_realize = dl_symbol("gtk_widget_realize");665fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy");666fp_gtk_widget_render_icon =667dl_symbol("gtk_widget_render_icon");668fp_gtk_widget_set_name =669dl_symbol("gtk_widget_set_name");670fp_gtk_widget_set_parent =671dl_symbol("gtk_widget_set_parent");672fp_gtk_widget_set_direction =673dl_symbol("gtk_widget_set_direction");674fp_gtk_widget_style_get =675dl_symbol("gtk_widget_style_get");676fp_gtk_widget_class_install_style_property =677dl_symbol("gtk_widget_class_install_style_property");678fp_gtk_widget_class_find_style_property =679dl_symbol("gtk_widget_class_find_style_property");680fp_gtk_widget_style_get_property =681dl_symbol("gtk_widget_style_get_property");682fp_pango_font_description_to_string =683dl_symbol("pango_font_description_to_string");684fp_gtk_settings_get_default =685dl_symbol("gtk_settings_get_default");686fp_gtk_widget_get_settings =687dl_symbol("gtk_widget_get_settings");688fp_gtk_border_get_type = dl_symbol("gtk_border_get_type");689fp_gtk_arrow_set = dl_symbol("gtk_arrow_set");690fp_gtk_widget_size_request =691dl_symbol("gtk_widget_size_request");692fp_gtk_range_get_adjustment =693dl_symbol("gtk_range_get_adjustment");694695fp_gtk_widget_hide = dl_symbol("gtk_widget_hide");696fp_gtk_main_quit = dl_symbol("gtk_main_quit");697fp_g_signal_connect_data = dl_symbol("g_signal_connect_data");698fp_gtk_widget_show = dl_symbol("gtk_widget_show");699fp_gtk_main = dl_symbol("gtk_main");700701fp_g_path_get_dirname = dl_symbol("g_path_get_dirname");702703/**704* GLib thread system705*/706if (GLIB_CHECK_VERSION(2, 20, 0)) {707fp_g_thread_get_initialized = dl_symbol_gthread("g_thread_get_initialized");708}709fp_g_thread_init = dl_symbol_gthread("g_thread_init");710fp_gdk_threads_init = dl_symbol("gdk_threads_init");711fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");712fp_gdk_threads_leave = dl_symbol("gdk_threads_leave");713714/**715* Functions for sun_awt_X11_GtkFileDialogPeer.c716*/717if (fp_gtk_check_version(2, 4, 0) == NULL) {718// The current GtkFileChooser is available from GTK+ 2.4719gtk2_file_chooser_load();720}721722/* Some functions may be missing in pre-2.4 GTK.723We handle them specially here.724*/725fp_gtk_combo_box_new = dlsym(gtk2_libhandle, "gtk_combo_box_new");726if (fp_gtk_combo_box_new == NULL) {727fp_gtk_combo_box_new = dl_symbol("gtk_combo_new");728}729730fp_gtk_combo_box_entry_new =731dlsym(gtk2_libhandle, "gtk_combo_box_entry_new");732if (fp_gtk_combo_box_entry_new == NULL) {733fp_gtk_combo_box_entry_new = dl_symbol("gtk_combo_new");734new_combo = FALSE;735}736737fp_gtk_separator_tool_item_new =738dlsym(gtk2_libhandle, "gtk_separator_tool_item_new");739if (fp_gtk_separator_tool_item_new == NULL) {740fp_gtk_separator_tool_item_new =741dl_symbol("gtk_vseparator_new");742}743744fp_g_list_append = dl_symbol("g_list_append");745fp_g_list_free = dl_symbol("g_list_free");746fp_g_list_free_full = dl_symbol("g_list_free_full");747}748/* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION749* Otherwise we can check the return value of setjmp method.750*/751else752{753dlclose(gtk2_libhandle);754gtk2_libhandle = NULL;755756dlclose(gthread_libhandle);757gthread_libhandle = NULL;758759return FALSE;760}761762/*763* Strip the AT-SPI GTK_MODULES if present764*/765gtk_modules_env = getenv ("GTK_MODULES");766if ((gtk_modules_env && strstr(gtk_modules_env, "atk-bridge")) ||767(gtk_modules_env && strstr(gtk_modules_env, "gail"))) {768/* careful, strtok modifies its args */769gchar *tmp_env = strdup(gtk_modules_env);770if (tmp_env) {771/* the new env will be smaller than the old one */772gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc,773sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env));774775if (new_env) {776strcpy(new_env, ENV_PREFIX);777778/* strip out 'atk-bridge' and 'gail' */779size_t PREFIX_LENGTH = strlen(ENV_PREFIX);780gchar *tmp_ptr = NULL;781for (s = strtok_r(tmp_env, ":", &tmp_ptr); s;782s = strtok_r(NULL, ":", &tmp_ptr)) {783if ((!strstr(s, "atk-bridge")) && (!strstr(s, "gail"))) {784if (strlen(new_env) > PREFIX_LENGTH) {785new_env = strcat(new_env, ":");786}787new_env = strcat(new_env, s);788}789}790if (putenv(new_env) != 0) {791/* no free() on success, putenv() doesn't copy string */792free(new_env);793}794}795free(tmp_env);796}797}798/*799* GTK should be initialized with gtk_init_check() before use.800*801* gtk_init_check installs its own error handlers. It is critical that802* we preserve error handler set from AWT. Otherwise we'll crash on803* BadMatch errors which we would normally ignore. The IO error handler804* is preserved here, too, just for consistency.805*/806AWT_LOCK();807handler = XSetErrorHandler(NULL);808io_handler = XSetIOErrorHandler(NULL);809810if (fp_gtk_check_version(2, 2, 0) == NULL) {811812// Calling g_thread_init() multiple times leads to crash on GLib < 2.24813// We can use g_thread_get_initialized () but it is available only for814// GLib >= 2.20.815gboolean is_g_thread_get_initialized = FALSE;816if (GLIB_CHECK_VERSION(2, 20, 0)) {817is_g_thread_get_initialized = fp_g_thread_get_initialized();818}819820if (!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}828result = (*fp_gtk_init_check)(NULL, NULL);829830XSetErrorHandler(handler);831XSetIOErrorHandler(io_handler);832AWT_UNLOCK();833834/* Initialize widget array. */835for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)836{837gtk2_widgets[i] = NULL;838}839if (result) {840GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi));841gtk2_init(gtk);842return gtk;843}844return NULL;845}846847int gtk2_unload()848{849int i;850char *gtk2_error;851852if (!gtk2_libhandle)853return TRUE;854855/* Release painting objects */856if (gtk2_white_pixmap != NULL) {857(*fp_g_object_unref)(gtk2_white_pixmap);858(*fp_g_object_unref)(gtk2_black_pixmap);859(*fp_g_object_unref)(gtk2_white_pixbuf);860(*fp_g_object_unref)(gtk2_black_pixbuf);861gtk2_white_pixmap = gtk2_black_pixmap =862gtk2_white_pixbuf = gtk2_black_pixbuf = NULL;863}864gtk2_pixbuf_width = 0;865gtk2_pixbuf_height = 0;866867if (gtk2_window != NULL) {868/* Destroying toplevel widget will destroy all contained widgets */869(*fp_gtk_widget_destroy)(gtk2_window);870871/* Unset some static data so they get reinitialized on next load */872gtk2_window = NULL;873}874875dlerror();876dlclose(gtk2_libhandle);877dlclose(gthread_libhandle);878if ((gtk2_error = dlerror()) != NULL)879{880return FALSE;881}882return TRUE;883}884885/* Dispatch all pending events from the GTK event loop.886* This is needed to catch theme change and update widgets' style.887*/888static void flush_gtk_event_loop()889{890while( (*fp_g_main_context_iteration)(NULL, FALSE));891}892893/*894* Initialize components of containment hierarchy. This creates a GtkFixed895* inside a GtkWindow. All widgets get realized.896*/897static void init_containers()898{899if (gtk2_window == NULL)900{901gtk2_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);902gtk2_fixed = (GtkFixed *)(*fp_gtk_fixed_new)();903(*fp_gtk_container_add)((GtkContainer*)gtk2_window,904(GtkWidget *)gtk2_fixed);905(*fp_gtk_widget_realize)(gtk2_window);906(*fp_gtk_widget_realize)((GtkWidget *)gtk2_fixed);907}908}909910/*911* Ensure everything is ready for drawing an element of the specified width912* and height.913*914* We should somehow handle translucent images. GTK can draw to X Drawables915* only, which don't support alpha. When we retrieve the image back from916* the server, translucency information is lost. There're several ways to917* work around this:918* 1) Subclass GdkPixmap and cache translucent objects on client side. This919* requires us to implement parts of X server drawing logic on client side.920* Many X requests can potentially be "translucent"; e.g. XDrawLine with921* fill=tile and a translucent tile is a "translucent" operation, whereas922* XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some923* do) intermix transparent and opaque operations which makes caching even924* more problematic.925* 2) Use Xorg 32bit ARGB visual when available. GDK has no native support926* for it (as of version 2.6). Also even in JDS 3 Xorg does not support927* these visuals by default, which makes optimizing for them pointless.928* We can consider doing this at a later point when ARGB visuals become more929* popular.930* 3') GTK has plans to use Cairo as its graphical backend (presumably in931* 2.8), and Cairo supports alpha. With it we could also get rid of the932* unnecessary round trip to server and do all the drawing on client side.933* 4) For now we draw to two different pixmaps and restore alpha channel by934* comparing results. This can be optimized by using subclassed pixmap and935* doing the second drawing only if necessary.936*/937static void gtk2_init_painting(JNIEnv *env, gint width, gint height)938{939GdkGC *gc;940GdkPixbuf *white, *black;941942init_containers();943944if (gtk2_pixbuf_width < width || gtk2_pixbuf_height < height)945{946white = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);947black = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);948949if (white == NULL || black == NULL)950{951snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height);952throw_exception(env, "java/lang/RuntimeException", convertionBuffer);953fp_gdk_threads_leave();954return;955}956957if (gtk2_white_pixmap != NULL) {958/* free old stuff */959(*fp_g_object_unref)(gtk2_white_pixmap);960(*fp_g_object_unref)(gtk2_black_pixmap);961(*fp_g_object_unref)(gtk2_white_pixbuf);962(*fp_g_object_unref)(gtk2_black_pixbuf);963}964965gtk2_white_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1);966gtk2_black_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1);967968gtk2_white_pixbuf = white;969gtk2_black_pixbuf = black;970971gtk2_pixbuf_width = width;972gtk2_pixbuf_height = height;973}974975/* clear the pixmaps */976gc = (*fp_gdk_gc_new)(gtk2_white_pixmap);977(*fp_gdk_rgb_gc_set_foreground)(gc, 0xffffff);978(*fp_gdk_draw_rectangle)(gtk2_white_pixmap, gc, TRUE, 0, 0, width, height);979(*fp_g_object_unref)(gc);980981gc = (*fp_gdk_gc_new)(gtk2_black_pixmap);982(*fp_gdk_rgb_gc_set_foreground)(gc, 0x000000);983(*fp_gdk_draw_rectangle)(gtk2_black_pixmap, gc, TRUE, 0, 0, width, height);984(*fp_g_object_unref)(gc);985}986987/*988* Restore image from white and black pixmaps and copy it into destination989* buffer. This method compares two pixbufs taken from white and black990* pixmaps and decodes color and alpha components. Pixbufs are RGB without991* alpha, destination buffer is ABGR.992*993* The return value is the transparency type of the resulting image, either994* one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and995* java_awt_Transparency_TRANSLUCENT.996*/997static gint gtk2_copy_image(gint *dst, gint width, gint height)998{999gint i, j, r, g, b;1000guchar *white, *black;1001gint stride, padding;1002gboolean is_opaque = TRUE;1003gboolean is_bitmask = TRUE;10041005(*fp_gdk_pixbuf_get_from_drawable)(gtk2_white_pixbuf, gtk2_white_pixmap,1006NULL, 0, 0, 0, 0, width, height);1007(*fp_gdk_pixbuf_get_from_drawable)(gtk2_black_pixbuf, gtk2_black_pixmap,1008NULL, 0, 0, 0, 0, width, height);10091010white = (*fp_gdk_pixbuf_get_pixels)(gtk2_white_pixbuf);1011black = (*fp_gdk_pixbuf_get_pixels)(gtk2_black_pixbuf);1012stride = (*fp_gdk_pixbuf_get_rowstride)(gtk2_black_pixbuf);1013padding = stride - width * 4;1014if (padding >= 0 && stride > 0) {1015for (i = 0; i < height; i++) {1016for (j = 0; j < width; j++) {1017int r1 = *white++;1018int r2 = *black++;1019int alpha = 0xff + r2 - r1;10201021switch (alpha) {1022case 0: /* transparent pixel */1023r = g = b = 0;1024black += 3;1025white += 3;1026is_opaque = FALSE;1027break;10281029case 0xff: /* opaque pixel */1030r = r2;1031g = *black++;1032b = *black++;1033black++;1034white += 3;1035break;10361037default: /* translucent pixel */1038r = 0xff * r2 / alpha;1039g = 0xff * *black++ / alpha;1040b = 0xff * *black++ / alpha;1041black++;1042white += 3;1043is_opaque = FALSE;1044is_bitmask = FALSE;1045break;1046}10471048*dst++ = (alpha << 24 | r << 16 | g << 8 | b);1049}10501051white += padding;1052black += padding;1053}1054}1055return is_opaque ? java_awt_Transparency_OPAQUE :1056(is_bitmask ? java_awt_Transparency_BITMASK :1057java_awt_Transparency_TRANSLUCENT);1058}10591060static void1061gtk2_set_direction(GtkWidget *widget, GtkTextDirection dir)1062{1063/*1064* Some engines (inexplicably) look at the direction of the widget's1065* parent, so we need to set the direction of both the widget and its1066* parent.1067*/1068(*fp_gtk_widget_set_direction)(widget, dir);1069if (widget->parent != NULL) {1070(*fp_gtk_widget_set_direction)(widget->parent, dir);1071}1072}10731074/*1075* Initializes the widget to correct state for some engines.1076* This is a pure empirical method.1077*/1078static void init_toggle_widget(WidgetType widget_type, gint synth_state)1079{1080gboolean is_active = ((synth_state & SELECTED) != 0);10811082if (widget_type == RADIO_BUTTON ||1083widget_type == CHECK_BOX ||1084widget_type == TOGGLE_BUTTON) {1085((GtkToggleButton*)gtk2_widget)->active = is_active;1086}10871088if ((synth_state & FOCUSED) != 0) {1089((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;1090} else {1091((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;1092}10931094if ((synth_state & MOUSE_OVER) != 0 && (synth_state & PRESSED) == 0 ||1095(synth_state & FOCUSED) != 0 && (synth_state & PRESSED) != 0) {1096gtk2_widget->state = GTK_STATE_PRELIGHT;1097} else if ((synth_state & DISABLED) != 0) {1098gtk2_widget->state = GTK_STATE_INSENSITIVE;1099} else {1100gtk2_widget->state = is_active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL;1101}1102}11031104/* GTK state_type filter */1105static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state)1106{1107GtkStateType result = GTK_STATE_NORMAL;11081109if ((synth_state & DISABLED) != 0) {1110result = GTK_STATE_INSENSITIVE;1111} else if ((synth_state & PRESSED) != 0) {1112result = GTK_STATE_ACTIVE;1113} else if ((synth_state & MOUSE_OVER) != 0) {1114result = GTK_STATE_PRELIGHT;1115}1116return result;1117}11181119/* GTK shadow_type filter */1120static GtkShadowType get_gtk_shadow_type(WidgetType widget_type, gint synth_state)1121{1122GtkShadowType result = GTK_SHADOW_OUT;11231124if ((synth_state & SELECTED) != 0) {1125result = GTK_SHADOW_IN;1126}1127return result;1128}112911301131static GtkWidget* gtk2_get_arrow(GtkArrowType arrow_type, GtkShadowType shadow_type)1132{1133GtkWidget *arrow = NULL;1134if (NULL == gtk2_widgets[_GTK_ARROW_TYPE])1135{1136gtk2_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type, shadow_type);1137(*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, gtk2_widgets[_GTK_ARROW_TYPE]);1138(*fp_gtk_widget_realize)(gtk2_widgets[_GTK_ARROW_TYPE]);1139}1140arrow = gtk2_widgets[_GTK_ARROW_TYPE];11411142(*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type);1143return arrow;1144}11451146static GtkAdjustment* create_adjustment()1147{1148return (GtkAdjustment *)1149(*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0);1150}11511152/**1153* Returns a pointer to the cached native widget for the specified widget1154* type.1155*/1156static GtkWidget *gtk2_get_widget(WidgetType widget_type)1157{1158gboolean init_result = FALSE;1159GtkWidget *result = NULL;1160switch (widget_type)1161{1162case BUTTON:1163case TABLE_HEADER:1164if (init_result = (NULL == gtk2_widgets[_GTK_BUTTON_TYPE]))1165{1166gtk2_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)();1167}1168result = gtk2_widgets[_GTK_BUTTON_TYPE];1169break;1170case CHECK_BOX:1171if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_BUTTON_TYPE]))1172{1173gtk2_widgets[_GTK_CHECK_BUTTON_TYPE] =1174(*fp_gtk_check_button_new)();1175}1176result = gtk2_widgets[_GTK_CHECK_BUTTON_TYPE];1177break;1178case CHECK_BOX_MENU_ITEM:1179if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE]))1180{1181gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE] =1182(*fp_gtk_check_menu_item_new)();1183}1184result = gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE];1185break;1186/************************************************************1187* Creation a dedicated color chooser is dangerous because1188* it deadlocks the EDT1189************************************************************/1190/* case COLOR_CHOOSER:1191if (init_result =1192(NULL == gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]))1193{1194gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] =1195(*fp_gtk_color_selection_dialog_new)(NULL);1196}1197result = gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE];1198break;*/1199case COMBO_BOX:1200if (init_result = (NULL == gtk2_widgets[_GTK_COMBO_BOX_TYPE]))1201{1202gtk2_widgets[_GTK_COMBO_BOX_TYPE] =1203(*fp_gtk_combo_box_new)();1204}1205result = gtk2_widgets[_GTK_COMBO_BOX_TYPE];1206break;1207case COMBO_BOX_ARROW_BUTTON:1208if (init_result =1209(NULL == gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]))1210{1211gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] =1212(*fp_gtk_toggle_button_new)();1213}1214result = gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE];1215break;1216case COMBO_BOX_TEXT_FIELD:1217if (init_result =1218(NULL == gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]))1219{1220result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] =1221(*fp_gtk_entry_new)();1222}1223result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE];1224break;1225case DESKTOP_ICON:1226case INTERNAL_FRAME_TITLE_PANE:1227case LABEL:1228if (init_result = (NULL == gtk2_widgets[_GTK_LABEL_TYPE]))1229{1230gtk2_widgets[_GTK_LABEL_TYPE] =1231(*fp_gtk_label_new)(NULL);1232}1233result = gtk2_widgets[_GTK_LABEL_TYPE];1234break;1235case DESKTOP_PANE:1236case PANEL:1237case ROOT_PANE:1238if (init_result = (NULL == gtk2_widgets[_GTK_CONTAINER_TYPE]))1239{1240/* There is no constructor for a container type. I've1241* chosen GtkFixed container since it has a default1242* constructor.1243*/1244gtk2_widgets[_GTK_CONTAINER_TYPE] =1245(*fp_gtk_fixed_new)();1246}1247result = gtk2_widgets[_GTK_CONTAINER_TYPE];1248break;1249case EDITOR_PANE:1250case TEXT_AREA:1251case TEXT_PANE:1252if (init_result = (NULL == gtk2_widgets[_GTK_TEXT_VIEW_TYPE]))1253{1254gtk2_widgets[_GTK_TEXT_VIEW_TYPE] =1255(*fp_gtk_text_view_new)();1256}1257result = gtk2_widgets[_GTK_TEXT_VIEW_TYPE];1258break;1259case FORMATTED_TEXT_FIELD:1260case PASSWORD_FIELD:1261case TEXT_FIELD:1262if (init_result = (NULL == gtk2_widgets[_GTK_ENTRY_TYPE]))1263{1264gtk2_widgets[_GTK_ENTRY_TYPE] =1265(*fp_gtk_entry_new)();1266}1267result = gtk2_widgets[_GTK_ENTRY_TYPE];1268break;1269case HANDLE_BOX:1270if (init_result = (NULL == gtk2_widgets[_GTK_HANDLE_BOX_TYPE]))1271{1272gtk2_widgets[_GTK_HANDLE_BOX_TYPE] =1273(*fp_gtk_handle_box_new)();1274}1275result = gtk2_widgets[_GTK_HANDLE_BOX_TYPE];1276break;1277case HSCROLL_BAR:1278case HSCROLL_BAR_BUTTON_LEFT:1279case HSCROLL_BAR_BUTTON_RIGHT:1280case HSCROLL_BAR_TRACK:1281case HSCROLL_BAR_THUMB:1282if (init_result = (NULL == gtk2_widgets[_GTK_HSCROLLBAR_TYPE]))1283{1284gtk2_widgets[_GTK_HSCROLLBAR_TYPE] =1285(*fp_gtk_hscrollbar_new)(create_adjustment());1286}1287result = gtk2_widgets[_GTK_HSCROLLBAR_TYPE];1288break;1289case HSEPARATOR:1290if (init_result = (NULL == gtk2_widgets[_GTK_HSEPARATOR_TYPE]))1291{1292gtk2_widgets[_GTK_HSEPARATOR_TYPE] =1293(*fp_gtk_hseparator_new)();1294}1295result = gtk2_widgets[_GTK_HSEPARATOR_TYPE];1296break;1297case HSLIDER:1298case HSLIDER_THUMB:1299case HSLIDER_TRACK:1300if (init_result = (NULL == gtk2_widgets[_GTK_HSCALE_TYPE]))1301{1302gtk2_widgets[_GTK_HSCALE_TYPE] =1303(*fp_gtk_hscale_new)(NULL);1304}1305result = gtk2_widgets[_GTK_HSCALE_TYPE];1306break;1307case HSPLIT_PANE_DIVIDER:1308case SPLIT_PANE:1309if (init_result = (NULL == gtk2_widgets[_GTK_HPANED_TYPE]))1310{1311gtk2_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)();1312}1313result = gtk2_widgets[_GTK_HPANED_TYPE];1314break;1315case IMAGE:1316if (init_result = (NULL == gtk2_widgets[_GTK_IMAGE_TYPE]))1317{1318gtk2_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)();1319}1320result = gtk2_widgets[_GTK_IMAGE_TYPE];1321break;1322case INTERNAL_FRAME:1323if (init_result = (NULL == gtk2_widgets[_GTK_WINDOW_TYPE]))1324{1325gtk2_widgets[_GTK_WINDOW_TYPE] =1326(*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);1327}1328result = gtk2_widgets[_GTK_WINDOW_TYPE];1329break;1330case TOOL_TIP:1331if (init_result = (NULL == gtk2_widgets[_GTK_TOOLTIP_TYPE]))1332{1333result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);1334(*fp_gtk_widget_set_name)(result, "gtk-tooltips");1335gtk2_widgets[_GTK_TOOLTIP_TYPE] = result;1336}1337result = gtk2_widgets[_GTK_TOOLTIP_TYPE];1338break;1339case LIST:1340case TABLE:1341case TREE:1342case TREE_CELL:1343if (init_result = (NULL == gtk2_widgets[_GTK_TREE_VIEW_TYPE]))1344{1345gtk2_widgets[_GTK_TREE_VIEW_TYPE] =1346(*fp_gtk_tree_view_new)();1347}1348result = gtk2_widgets[_GTK_TREE_VIEW_TYPE];1349break;1350case TITLED_BORDER:1351if (init_result = (NULL == gtk2_widgets[_GTK_FRAME_TYPE]))1352{1353gtk2_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL);1354}1355result = gtk2_widgets[_GTK_FRAME_TYPE];1356break;1357case POPUP_MENU:1358if (init_result = (NULL == gtk2_widgets[_GTK_MENU_TYPE]))1359{1360gtk2_widgets[_GTK_MENU_TYPE] =1361(*fp_gtk_menu_new)();1362}1363result = gtk2_widgets[_GTK_MENU_TYPE];1364break;1365case MENU:1366case MENU_ITEM:1367case MENU_ITEM_ACCELERATOR:1368if (init_result = (NULL == gtk2_widgets[_GTK_MENU_ITEM_TYPE]))1369{1370gtk2_widgets[_GTK_MENU_ITEM_TYPE] =1371(*fp_gtk_menu_item_new)();1372}1373result = gtk2_widgets[_GTK_MENU_ITEM_TYPE];1374break;1375case MENU_BAR:1376if (init_result = (NULL == gtk2_widgets[_GTK_MENU_BAR_TYPE]))1377{1378gtk2_widgets[_GTK_MENU_BAR_TYPE] =1379(*fp_gtk_menu_bar_new)();1380}1381result = gtk2_widgets[_GTK_MENU_BAR_TYPE];1382break;1383case COLOR_CHOOSER:1384case OPTION_PANE:1385if (init_result = (NULL == gtk2_widgets[_GTK_DIALOG_TYPE]))1386{1387gtk2_widgets[_GTK_DIALOG_TYPE] =1388(*fp_gtk_dialog_new)();1389}1390result = gtk2_widgets[_GTK_DIALOG_TYPE];1391break;1392case POPUP_MENU_SEPARATOR:1393if (init_result =1394(NULL == gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]))1395{1396gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] =1397(*fp_gtk_separator_menu_item_new)();1398}1399result = gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE];1400break;1401case HPROGRESS_BAR:1402if (init_result = (NULL == gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE]))1403{1404gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE] =1405(*fp_gtk_progress_bar_new)();1406}1407result = gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE];1408break;1409case VPROGRESS_BAR:1410if (init_result = (NULL == gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE]))1411{1412gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE] =1413(*fp_gtk_progress_bar_new)();1414/*1415* Vertical JProgressBars always go bottom-to-top,1416* regardless of the ComponentOrientation.1417*/1418(*fp_gtk_progress_bar_set_orientation)(1419(GtkProgressBar *)gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE],1420GTK_PROGRESS_BOTTOM_TO_TOP);1421}1422result = gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE];1423break;1424case RADIO_BUTTON:1425if (init_result = (NULL == gtk2_widgets[_GTK_RADIO_BUTTON_TYPE]))1426{1427gtk2_widgets[_GTK_RADIO_BUTTON_TYPE] =1428(*fp_gtk_radio_button_new)(NULL);1429}1430result = gtk2_widgets[_GTK_RADIO_BUTTON_TYPE];1431break;1432case RADIO_BUTTON_MENU_ITEM:1433if (init_result =1434(NULL == gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE]))1435{1436gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE] =1437(*fp_gtk_radio_menu_item_new)(NULL);1438}1439result = gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE];1440break;1441case SCROLL_PANE:1442if (init_result =1443(NULL == gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE]))1444{1445gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE] =1446(*fp_gtk_scrolled_window_new)(NULL, NULL);1447}1448result = gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE];1449break;1450case SPINNER:1451case SPINNER_ARROW_BUTTON:1452case SPINNER_TEXT_FIELD:1453if (init_result = (NULL == gtk2_widgets[_GTK_SPIN_BUTTON_TYPE]))1454{1455result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE] =1456(*fp_gtk_spin_button_new)(NULL, 0, 0);1457}1458result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE];1459break;1460case TABBED_PANE:1461case TABBED_PANE_TAB_AREA:1462case TABBED_PANE_CONTENT:1463case TABBED_PANE_TAB:1464if (init_result = (NULL == gtk2_widgets[_GTK_NOTEBOOK_TYPE]))1465{1466gtk2_widgets[_GTK_NOTEBOOK_TYPE] =1467(*fp_gtk_notebook_new)(NULL);1468}1469result = gtk2_widgets[_GTK_NOTEBOOK_TYPE];1470break;1471case TOGGLE_BUTTON:1472if (init_result = (NULL == gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE]))1473{1474gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE] =1475(*fp_gtk_toggle_button_new)(NULL);1476}1477result = gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE];1478break;1479case TOOL_BAR:1480case TOOL_BAR_DRAG_WINDOW:1481if (init_result = (NULL == gtk2_widgets[_GTK_TOOLBAR_TYPE]))1482{1483gtk2_widgets[_GTK_TOOLBAR_TYPE] =1484(*fp_gtk_toolbar_new)(NULL);1485}1486result = gtk2_widgets[_GTK_TOOLBAR_TYPE];1487break;1488case TOOL_BAR_SEPARATOR:1489if (init_result =1490(NULL == gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]))1491{1492gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] =1493(*fp_gtk_separator_tool_item_new)();1494}1495result = gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE];1496break;1497case VIEWPORT:1498if (init_result = (NULL == gtk2_widgets[_GTK_VIEWPORT_TYPE]))1499{1500GtkAdjustment *adjustment = create_adjustment();1501gtk2_widgets[_GTK_VIEWPORT_TYPE] =1502(*fp_gtk_viewport_new)(adjustment, adjustment);1503}1504result = gtk2_widgets[_GTK_VIEWPORT_TYPE];1505break;1506case VSCROLL_BAR:1507case VSCROLL_BAR_BUTTON_UP:1508case VSCROLL_BAR_BUTTON_DOWN:1509case VSCROLL_BAR_TRACK:1510case VSCROLL_BAR_THUMB:1511if (init_result = (NULL == gtk2_widgets[_GTK_VSCROLLBAR_TYPE]))1512{1513gtk2_widgets[_GTK_VSCROLLBAR_TYPE] =1514(*fp_gtk_vscrollbar_new)(create_adjustment());1515}1516result = gtk2_widgets[_GTK_VSCROLLBAR_TYPE];1517break;1518case VSEPARATOR:1519if (init_result = (NULL == gtk2_widgets[_GTK_VSEPARATOR_TYPE]))1520{1521gtk2_widgets[_GTK_VSEPARATOR_TYPE] =1522(*fp_gtk_vseparator_new)();1523}1524result = gtk2_widgets[_GTK_VSEPARATOR_TYPE];1525break;1526case VSLIDER:1527case VSLIDER_THUMB:1528case VSLIDER_TRACK:1529if (init_result = (NULL == gtk2_widgets[_GTK_VSCALE_TYPE]))1530{1531gtk2_widgets[_GTK_VSCALE_TYPE] =1532(*fp_gtk_vscale_new)(NULL);1533}1534result = gtk2_widgets[_GTK_VSCALE_TYPE];1535/*1536* Vertical JSliders start at the bottom, while vertical1537* GtkVScale widgets start at the top (by default), so to fix1538* this we set the "inverted" flag to get the Swing behavior.1539*/1540((GtkRange*)result)->inverted = 1;1541break;1542case VSPLIT_PANE_DIVIDER:1543if (init_result = (NULL == gtk2_widgets[_GTK_VPANED_TYPE]))1544{1545gtk2_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)();1546}1547result = gtk2_widgets[_GTK_VPANED_TYPE];1548break;1549default:1550result = NULL;1551break;1552}15531554if (result != NULL && init_result)1555{1556if (widget_type == RADIO_BUTTON_MENU_ITEM ||1557widget_type == CHECK_BOX_MENU_ITEM ||1558widget_type == MENU_ITEM ||1559widget_type == MENU ||1560widget_type == POPUP_MENU_SEPARATOR)1561{1562GtkWidget *menu = gtk2_get_widget(POPUP_MENU);1563(*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result);1564}1565else if (widget_type == POPUP_MENU)1566{1567GtkWidget *menu_bar = gtk2_get_widget(MENU_BAR);1568GtkWidget *root_menu = (*fp_gtk_menu_item_new)();1569(*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result);1570(*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu);1571}1572else if (widget_type == COMBO_BOX_ARROW_BUTTON ||1573widget_type == COMBO_BOX_TEXT_FIELD)1574{1575/*1576* We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry1577* in order to trick engines into thinking it's a real combobox1578* arrow button/text field.1579*/1580GtkWidget *combo = (*fp_gtk_combo_box_entry_new)();15811582if (new_combo && widget_type == COMBO_BOX_ARROW_BUTTON) {1583(*fp_gtk_widget_set_parent)(result, combo);1584((GtkBin*)combo)->child = result;1585} else {1586(*fp_gtk_container_add)((GtkContainer *)combo, result);1587}1588(*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, combo);1589}1590else if (widget_type != TOOL_TIP &&1591widget_type != INTERNAL_FRAME &&1592widget_type != OPTION_PANE)1593{1594(*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, result);1595}1596(*fp_gtk_widget_realize)(result);1597}1598return result;1599}16001601void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type,1602GtkShadowType shadow_type, const gchar *detail,1603gint x, gint y, gint width, gint height,1604GtkArrowType arrow_type, gboolean fill)1605{1606static int w, h;1607static GtkRequisition size;16081609if (widget_type == COMBO_BOX_ARROW_BUTTON || widget_type == TABLE)1610gtk2_widget = gtk2_get_arrow(arrow_type, shadow_type);1611else1612gtk2_widget = gtk2_get_widget(widget_type);16131614switch (widget_type)1615{1616case SPINNER_ARROW_BUTTON:1617x = 1;1618y = ((arrow_type == GTK_ARROW_UP) ? 2 : 0);1619height -= 2;1620width -= 3;16211622w = width / 2;1623w -= w % 2 - 1;1624h = (w + 1) / 2;1625break;16261627case HSCROLL_BAR_BUTTON_LEFT:1628case HSCROLL_BAR_BUTTON_RIGHT:1629case VSCROLL_BAR_BUTTON_UP:1630case VSCROLL_BAR_BUTTON_DOWN:1631w = width / 2;1632h = height / 2;1633break;16341635case COMBO_BOX_ARROW_BUTTON:1636case TABLE:1637x = 1;1638(*fp_gtk_widget_size_request)(gtk2_widget, &size);1639w = size.width - ((GtkMisc*)gtk2_widget)->xpad * 2;1640h = size.height - ((GtkMisc*)gtk2_widget)->ypad * 2;1641w = h = MIN(MIN(w, h), MIN(width,height)) * 0.7;1642break;16431644default:1645w = width;1646h = height;1647break;1648}1649x += (width - w) / 2;1650y += (height - h) / 2;16511652(*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_white_pixmap, state_type,1653shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,1654x, y, w, h);1655(*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_black_pixmap, state_type,1656shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,1657x, y, w, h);1658}16591660static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,1661GtkShadowType shadow_type, const gchar *detail,1662gint x, gint y, gint width, gint height,1663gint synth_state, GtkTextDirection dir)1664{1665gtk2_widget = gtk2_get_widget(widget_type);16661667/*1668* The clearlooks engine sometimes looks at the widget's state field1669* instead of just the state_type variable that we pass in, so to account1670* for those cases we set the widget's state field accordingly. The1671* flags field is similarly important for things like focus/default state.1672*/1673gtk2_widget->state = state_type;16741675if (widget_type == HSLIDER_TRACK) {1676/*1677* For horizontal JSliders with right-to-left orientation, we need1678* to set the "inverted" flag to match the native GTK behavior where1679* the foreground highlight is on the right side of the slider thumb.1680* This is needed especially for the ubuntulooks engine, which looks1681* exclusively at the "inverted" flag to determine on which side of1682* the thumb to paint the highlight...1683*/1684((GtkRange*)gtk2_widget)->inverted = (dir == GTK_TEXT_DIR_RTL);16851686/*1687* Note however that other engines like clearlooks will look at both1688* the "inverted" field and the text direction to determine how1689* the foreground highlight is painted:1690* !inverted && ltr --> paint highlight on left side1691* !inverted && rtl --> paint highlight on right side1692* inverted && ltr --> paint highlight on right side1693* inverted && rtl --> paint highlight on left side1694* So the only way to reliably get the desired results for horizontal1695* JSlider (i.e., highlight on left side for LTR ComponentOrientation1696* and highlight on right side for RTL ComponentOrientation) is to1697* always override text direction as LTR, and then set the "inverted"1698* flag accordingly (as we have done above).1699*/1700dir = GTK_TEXT_DIR_LTR;1701}17021703/*1704* Some engines (e.g. clearlooks) will paint the shadow of certain1705* widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the1706* the text direction.1707*/1708gtk2_set_direction(gtk2_widget, dir);17091710switch (widget_type) {1711case BUTTON:1712if (synth_state & DEFAULT) {1713((GtkObject*)gtk2_widget)->flags |= GTK_HAS_DEFAULT;1714} else {1715((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_DEFAULT;1716}1717break;1718case TOGGLE_BUTTON:1719init_toggle_widget(widget_type, synth_state);1720break;1721case HSCROLL_BAR_BUTTON_LEFT:1722/*1723* The clearlooks engine will draw a "left" button when:1724* x == w->allocation.x1725*1726* The ubuntulooks engine will draw a "left" button when:1727* [x,y,width,height]1728* intersects1729* [w->alloc.x,w->alloc.y,width,height]1730*1731* The values that are set below should ensure that a "left"1732* button is rendered for both of these (and other) engines.1733*/1734gtk2_widget->allocation.x = x;1735gtk2_widget->allocation.y = y;1736gtk2_widget->allocation.width = width;1737gtk2_widget->allocation.height = height;1738break;1739case HSCROLL_BAR_BUTTON_RIGHT:1740/*1741* The clearlooks engine will draw a "right" button when:1742* x + width == w->allocation.x + w->allocation.width1743*1744* The ubuntulooks engine will draw a "right" button when:1745* [x,y,width,height]1746* does not intersect1747* [w->alloc.x,w->alloc.y,width,height]1748* but does intersect1749* [w->alloc.x+width,w->alloc.y,width,height]1750*1751* The values that are set below should ensure that a "right"1752* button is rendered for both of these (and other) engines.1753*/1754gtk2_widget->allocation.x = x+width;1755gtk2_widget->allocation.y = 0;1756gtk2_widget->allocation.width = 0;1757gtk2_widget->allocation.height = height;1758break;1759case VSCROLL_BAR_BUTTON_UP:1760/*1761* The clearlooks engine will draw an "up" button when:1762* y == w->allocation.y1763*1764* The ubuntulooks engine will draw an "up" button when:1765* [x,y,width,height]1766* intersects1767* [w->alloc.x,w->alloc.y,width,height]1768*1769* The values that are set below should ensure that an "up"1770* button is rendered for both of these (and other) engines.1771*/1772gtk2_widget->allocation.x = x;1773gtk2_widget->allocation.y = y;1774gtk2_widget->allocation.width = width;1775gtk2_widget->allocation.height = height;1776break;1777case VSCROLL_BAR_BUTTON_DOWN:1778/*1779* The clearlooks engine will draw a "down" button when:1780* y + height == w->allocation.y + w->allocation.height1781*1782* The ubuntulooks engine will draw a "down" button when:1783* [x,y,width,height]1784* does not intersect1785* [w->alloc.x,w->alloc.y,width,height]1786* but does intersect1787* [w->alloc.x,w->alloc.y+height,width,height]1788*1789* The values that are set below should ensure that a "down"1790* button is rendered for both of these (and other) engines.1791*/1792gtk2_widget->allocation.x = x;1793gtk2_widget->allocation.y = y+height;1794gtk2_widget->allocation.width = width;1795gtk2_widget->allocation.height = 0;1796break;1797default:1798break;1799}18001801(*fp_gtk_paint_box)(gtk2_widget->style, gtk2_white_pixmap, state_type,1802shadow_type, NULL, gtk2_widget, detail, x, y, width, height);1803(*fp_gtk_paint_box)(gtk2_widget->style, gtk2_black_pixmap, state_type,1804shadow_type, NULL, gtk2_widget, detail, x, y, width, height);18051806/*1807* Reset the text direction to the default value so that we don't1808* accidentally affect other operations and widgets.1809*/1810gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);1811}18121813void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type,1814GtkShadowType shadow_type, const gchar *detail,1815gint x, gint y, gint width, gint height,1816GtkPositionType gap_side, gint gap_x, gint gap_width)1817{1818/* Clearlooks needs a real clip area to paint the gap properly */1819GdkRectangle area = { x, y, width, height };18201821gtk2_widget = gtk2_get_widget(widget_type);1822(*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_white_pixmap, state_type,1823shadow_type, &area, gtk2_widget, detail,1824x, y, width, height, gap_side, gap_x, gap_width);1825(*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_black_pixmap, state_type,1826shadow_type, &area, gtk2_widget, detail,1827x, y, width, height, gap_side, gap_x, gap_width);1828}18291830static void gtk2_paint_check(WidgetType widget_type, gint synth_state,1831const gchar *detail, gint x, gint y, gint width, gint height)1832{1833GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);1834GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);18351836gtk2_widget = gtk2_get_widget(widget_type);1837init_toggle_widget(widget_type, synth_state);18381839(*fp_gtk_paint_check)(gtk2_widget->style, gtk2_white_pixmap, state_type,1840shadow_type, NULL, gtk2_widget, detail,1841x, y, width, height);1842(*fp_gtk_paint_check)(gtk2_widget->style, gtk2_black_pixmap, state_type,1843shadow_type, NULL, gtk2_widget, detail,1844x, y, width, height);1845}18461847static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,1848const gchar *detail, gint x, gint y, gint width, gint height,1849GtkExpanderStyle expander_style)1850{1851gtk2_widget = gtk2_get_widget(widget_type);1852(*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_white_pixmap,1853state_type, NULL, gtk2_widget, detail,1854x + width / 2, y + height / 2, expander_style);1855(*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_black_pixmap,1856state_type, NULL, gtk2_widget, detail,1857x + width / 2, y + height / 2, expander_style);1858}18591860static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,1861GtkShadowType shadow_type, const gchar *detail,1862gint x, gint y, gint width, gint height, GtkPositionType gap_side)1863{1864gtk2_widget = gtk2_get_widget(widget_type);1865(*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_white_pixmap,1866state_type, shadow_type, NULL, gtk2_widget, detail,1867x, y, width, height, gap_side);1868(*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_black_pixmap,1869state_type, shadow_type, NULL, gtk2_widget, detail,1870x, y, width, height, gap_side);1871}18721873static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,1874GtkShadowType shadow_type, const gchar *detail,1875gint x, gint y, gint width, gint height, gboolean has_focus)1876{1877gtk2_widget = gtk2_get_widget(widget_type);18781879if (has_focus)1880((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;1881else1882((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;18831884(*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_white_pixmap,1885state_type, shadow_type, NULL, gtk2_widget, detail,1886x, y, width, height);1887(*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_black_pixmap,1888state_type, shadow_type, NULL, gtk2_widget, detail,1889x, y, width, height);1890}18911892static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,1893const char *detail, gint x, gint y, gint width, gint height)1894{1895gtk2_widget = gtk2_get_widget(widget_type);1896(*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_white_pixmap, state_type,1897NULL, gtk2_widget, detail, x, y, width, height);1898(*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_black_pixmap, state_type,1899NULL, gtk2_widget, detail, x, y, width, height);1900}19011902static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,1903GtkShadowType shadow_type, const gchar *detail,1904gint x, gint y, gint width, gint height, GtkOrientation orientation)1905{1906gtk2_widget = gtk2_get_widget(widget_type);1907(*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_white_pixmap, state_type,1908shadow_type, NULL, gtk2_widget, detail,1909x, y, width, height, orientation);1910(*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_black_pixmap, state_type,1911shadow_type, NULL, gtk2_widget, detail,1912x, y, width, height, orientation);1913}19141915static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,1916const gchar *detail, gint x, gint y, gint width, gint height)1917{1918gtk2_widget = gtk2_get_widget(widget_type);1919(*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_white_pixmap, state_type,1920NULL, gtk2_widget, detail, x, x + width, y);1921(*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_black_pixmap, state_type,1922NULL, gtk2_widget, detail, x, x + width, y);1923}19241925static void gtk2_paint_option(WidgetType widget_type, gint synth_state,1926const gchar *detail, gint x, gint y, gint width, gint height)1927{1928GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);1929GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);19301931gtk2_widget = gtk2_get_widget(widget_type);1932init_toggle_widget(widget_type, synth_state);19331934(*fp_gtk_paint_option)(gtk2_widget->style, gtk2_white_pixmap, state_type,1935shadow_type, NULL, gtk2_widget, detail,1936x, y, width, height);1937(*fp_gtk_paint_option)(gtk2_widget->style, gtk2_black_pixmap, state_type,1938shadow_type, NULL, gtk2_widget, detail,1939x, y, width, height);1940}19411942static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,1943GtkShadowType shadow_type, const gchar *detail,1944gint x, gint y, gint width, gint height,1945gint synth_state, GtkTextDirection dir)1946{1947gtk2_widget = gtk2_get_widget(widget_type);19481949/*1950* The clearlooks engine sometimes looks at the widget's state field1951* instead of just the state_type variable that we pass in, so to account1952* for those cases we set the widget's state field accordingly. The1953* flags field is similarly important for things like focus state.1954*/1955gtk2_widget->state = state_type;19561957/*1958* Some engines (e.g. clearlooks) will paint the shadow of certain1959* widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the1960* the text direction.1961*/1962gtk2_set_direction(gtk2_widget, dir);19631964switch (widget_type) {1965case COMBO_BOX_TEXT_FIELD:1966case FORMATTED_TEXT_FIELD:1967case PASSWORD_FIELD:1968case SPINNER_TEXT_FIELD:1969case TEXT_FIELD:1970if (synth_state & FOCUSED) {1971((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;1972} else {1973((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;1974}1975break;1976default:1977break;1978}19791980(*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_white_pixmap, state_type,1981shadow_type, NULL, gtk2_widget, detail, x, y, width, height);1982(*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_black_pixmap, state_type,1983shadow_type, NULL, gtk2_widget, detail, x, y, width, height);19841985/*1986* Reset the text direction to the default value so that we don't1987* accidentally affect other operations and widgets.1988*/1989gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);1990}19911992static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,1993GtkShadowType shadow_type, const gchar *detail,1994gint x, gint y, gint width, gint height, GtkOrientation orientation,1995gboolean has_focus)1996{1997gtk2_widget = gtk2_get_widget(widget_type);1998(*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type,1999shadow_type, NULL, gtk2_widget, detail,2000x, y, width, height, orientation);2001(*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_black_pixmap, state_type,2002shadow_type, NULL, gtk2_widget, detail,2003x, y, width, height, orientation);2004}20052006static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,2007const gchar *detail, gint x, gint y, gint width, gint height)2008{2009gtk2_widget = gtk2_get_widget(widget_type);2010(*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_white_pixmap, state_type,2011NULL, gtk2_widget, detail, y, y + height, x);2012(*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_black_pixmap, state_type,2013NULL, gtk2_widget, detail, y, y + height, x);2014}20152016static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,2017gint x, gint y, gint width, gint height)2018{2019gtk2_widget = gtk2_get_widget(widget_type);2020(*fp_gtk_style_apply_default_background)(gtk2_widget->style,2021gtk2_white_pixmap, TRUE, state_type, NULL, x, y, width, height);2022(*fp_gtk_style_apply_default_background)(gtk2_widget->style,2023gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height);2024}20252026static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,2027GtkIconSize size, GtkTextDirection direction, const char *detail)2028{2029init_containers();2030gtk2_widget = gtk2_get_widget((widget_type < 0) ? IMAGE : widget_type);2031gtk2_widget->state = GTK_STATE_NORMAL;2032(*fp_gtk_widget_set_direction)(gtk2_widget, direction);2033return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail);2034}20352036static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf,2037jmethodID icon_upcall_method, jobject this) {2038if (!pixbuf) {2039return JNI_FALSE;2040}2041guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);2042if (pixbuf_data) {2043int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);2044int width = (*fp_gdk_pixbuf_get_width)(pixbuf);2045int height = (*fp_gdk_pixbuf_get_height)(pixbuf);2046int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);2047int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);2048gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);20492050jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));2051JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);20522053(*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),2054(jbyte *)pixbuf_data);2055(*fp_g_object_unref)(pixbuf);20562057/* Call the callback method to create the image on the Java side. */2058(*env)->CallVoidMethod(env, this, icon_upcall_method, data,2059width, height, row_stride, bps, channels, alpha);2060return JNI_TRUE;2061}2062return JNI_FALSE;2063}20642065static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename,2066GError **error, jmethodID icon_upcall_method, jobject this) {2067GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error);2068return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);2069}20702071static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type,2072const gchar *stock_id, GtkIconSize size,2073GtkTextDirection direction, const char *detail,2074jmethodID icon_upcall_method, jobject this) {2075GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size,2076direction, detail);2077return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);2078}20792080/*************************************************/2081static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type)2082{2083init_containers();20842085gtk2_widget = gtk2_get_widget(widget_type);2086GtkStyle* style = gtk2_widget->style;2087return style->xthickness;2088}20892090static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type)2091{2092init_containers();20932094gtk2_widget = gtk2_get_widget(widget_type);2095GtkStyle* style = gtk2_widget->style;2096return style->ythickness;2097}20982099/*************************************************/2100static guint8 recode_color(guint16 channel)2101{2102return (guint8)(channel>>8);2103}21042105static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,2106GtkStateType state_type, ColorType color_type)2107{2108gint result = 0;2109GdkColor *color = NULL;21102111init_containers();21122113gtk2_widget = gtk2_get_widget(widget_type);2114GtkStyle* style = gtk2_widget->style;21152116switch (color_type)2117{2118case FOREGROUND:2119color = &(style->fg[state_type]);2120break;2121case BACKGROUND:2122color = &(style->bg[state_type]);2123break;2124case TEXT_FOREGROUND:2125color = &(style->text[state_type]);2126break;2127case TEXT_BACKGROUND:2128color = &(style->base[state_type]);2129break;2130case LIGHT:2131color = &(style->light[state_type]);2132break;2133case DARK:2134color = &(style->dark[state_type]);2135break;2136case MID:2137color = &(style->mid[state_type]);2138break;2139case FOCUS:2140case BLACK:2141color = &(style->black);2142break;2143case WHITE:2144color = &(style->white);2145break;2146}21472148if (color)2149result = recode_color(color->red) << 16 |2150recode_color(color->green) << 8 |2151recode_color(color->blue);21522153return result;2154}21552156/*************************************************/2157static jobject create_Boolean(JNIEnv *env, jboolean boolean_value);2158static jobject create_Integer(JNIEnv *env, jint int_value);2159static jobject create_Long(JNIEnv *env, jlong long_value);2160static jobject create_Float(JNIEnv *env, jfloat float_value);2161static jobject create_Double(JNIEnv *env, jdouble double_value);2162static jobject create_Character(JNIEnv *env, jchar char_value);2163static jobject create_Insets(JNIEnv *env, GtkBorder *border);21642165static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type,2166const char* key)2167{2168init_containers();21692170gtk2_widget = gtk2_get_widget(widget_type);21712172GValue value;2173value.g_type = 0;21742175GParamSpec* param = (*fp_gtk_widget_class_find_style_property)(2176((GTypeInstance*)gtk2_widget)->g_class, key);2177if( param )2178{2179(*fp_g_value_init)( &value, param->value_type );2180(*fp_gtk_widget_style_get_property)(gtk2_widget, key, &value);21812182if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN ))2183{2184gboolean val = (*fp_g_value_get_boolean)(&value);2185return create_Boolean(env, (jboolean)val);2186}2187else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR ))2188{2189gchar val = (*fp_g_value_get_char)(&value);2190return create_Character(env, (jchar)val);2191}2192else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR ))2193{2194guchar val = (*fp_g_value_get_uchar)(&value);2195return create_Character(env, (jchar)val);2196}2197else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT ))2198{2199gint val = (*fp_g_value_get_int)(&value);2200return create_Integer(env, (jint)val);2201}2202else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT ))2203{2204guint val = (*fp_g_value_get_uint)(&value);2205return create_Integer(env, (jint)val);2206}2207else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_LONG ))2208{2209glong val = (*fp_g_value_get_long)(&value);2210return create_Long(env, (jlong)val);2211}2212else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG ))2213{2214gulong val = (*fp_g_value_get_ulong)(&value);2215return create_Long(env, (jlong)val);2216}2217else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 ))2218{2219gint64 val = (*fp_g_value_get_int64)(&value);2220return create_Long(env, (jlong)val);2221}2222else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 ))2223{2224guint64 val = (*fp_g_value_get_uint64)(&value);2225return create_Long(env, (jlong)val);2226}2227else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT ))2228{2229gfloat val = (*fp_g_value_get_float)(&value);2230return create_Float(env, (jfloat)val);2231}2232else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE ))2233{2234gdouble val = (*fp_g_value_get_double)(&value);2235return create_Double(env, (jdouble)val);2236}2237else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM ))2238{2239gint val = (*fp_g_value_get_enum)(&value);2240return create_Integer(env, (jint)val);2241}2242else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS ))2243{2244guint val = (*fp_g_value_get_flags)(&value);2245return create_Integer(env, (jint)val);2246}2247else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_STRING ))2248{2249const gchar* val = (*fp_g_value_get_string)(&value);22502251/* We suppose that all values come in C locale and2252* utf-8 representation of a string is the same as2253* the string itself. If this isn't so we should2254* use g_convert.2255*/2256return (*env)->NewStringUTF(env, val);2257}2258else if( (*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER ))2259{2260GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value);2261return border ? create_Insets(env, border) : NULL;2262}22632264/* TODO: Other types are not supported yet.*/2265/* else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM ))2266{2267GParamSpec* val = (*fp_g_value_get_param)(&value);2268printf( "Param: %p\n", val );2269}2270else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED ))2271{2272gpointer* val = (*fp_g_value_get_boxed)(&value);2273printf( "Boxed: %p\n", val );2274}2275else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER ))2276{2277gpointer* val = (*fp_g_value_get_pointer)(&value);2278printf( "Pointer: %p\n", val );2279}2280else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT ))2281{2282GObject* val = (GObject*)(*fp_g_value_get_object)(&value);2283printf( "Object: %p\n", val );2284}*/2285}22862287return NULL;2288}22892290static void gtk2_set_range_value(WidgetType widget_type, jdouble value,2291jdouble min, jdouble max, jdouble visible)2292{2293GtkAdjustment *adj;22942295gtk2_widget = gtk2_get_widget(widget_type);22962297adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk2_widget);2298adj->value = (gdouble)value;2299adj->lower = (gdouble)min;2300adj->upper = (gdouble)max;2301adj->page_size = (gdouble)visible;2302}23032304/*************************************************/2305static jobject create_Object(JNIEnv *env, jmethodID *cid,2306const char* class_name,2307const char* signature,2308jvalue* value)2309{2310jclass class;2311jobject result;23122313class = (*env)->FindClass(env, class_name);2314if( class == NULL )2315return NULL; /* can't find/load the class, exception thrown */23162317if( *cid == NULL)2318{2319*cid = (*env)->GetMethodID(env, class, "<init>", signature);2320if( *cid == NULL )2321{2322(*env)->DeleteLocalRef(env, class);2323return NULL; /* can't find/get the method, exception thrown */2324}2325}23262327result = (*env)->NewObjectA(env, class, *cid, value);23282329(*env)->DeleteLocalRef(env, class);2330return result;2331}23322333jobject create_Boolean(JNIEnv *env, jboolean boolean_value)2334{2335static jmethodID cid = NULL;2336jvalue value;23372338value.z = boolean_value;23392340return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value);2341}23422343jobject create_Integer(JNIEnv *env, jint int_value)2344{2345static jmethodID cid = NULL;2346jvalue value;23472348value.i = int_value;23492350return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value);2351}23522353jobject create_Long(JNIEnv *env, jlong long_value)2354{2355static jmethodID cid = NULL;2356jvalue value;23572358value.j = long_value;23592360return create_Object(env, &cid, "java/lang/Long", "(J)V", &value);2361}23622363jobject create_Float(JNIEnv *env, jfloat float_value)2364{2365static jmethodID cid = NULL;2366jvalue value;23672368value.f = float_value;23692370return create_Object(env, &cid, "java/lang/Float", "(F)V", &value);2371}23722373jobject create_Double(JNIEnv *env, jdouble double_value)2374{2375static jmethodID cid = NULL;2376jvalue value;23772378value.d = double_value;23792380return create_Object(env, &cid, "java/lang/Double", "(D)V", &value);2381}23822383jobject create_Character(JNIEnv *env, jchar char_value)2384{2385static jmethodID cid = NULL;2386jvalue value;23872388value.c = char_value;23892390return create_Object(env, &cid, "java/lang/Character", "(C)V", &value);2391}239223932394jobject create_Insets(JNIEnv *env, GtkBorder *border)2395{2396static jmethodID cid = NULL;2397jvalue values[4];23982399values[0].i = border->top;2400values[1].i = border->left;2401values[2].i = border->bottom;2402values[3].i = border->right;24032404return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values);2405}24062407/*********************************************/2408static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type)2409{2410init_containers();24112412gtk2_widget = gtk2_get_widget(widget_type);2413jstring result = NULL;2414GtkStyle* style = gtk2_widget->style;24152416if (style && style->font_desc)2417{2418gchar* val = (*fp_pango_font_description_to_string)(style->font_desc);2419result = (*env)->NewStringUTF(env, val);2420(*fp_g_free)( val );2421}24222423return result;2424}24252426/***********************************************/2427static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key)2428{2429jobject result = NULL;2430gchar* strval = NULL;24312432(*fp_g_object_get)(settings, key, &strval, NULL);2433result = (*env)->NewStringUTF(env, strval);2434(*fp_g_free)(strval);24352436return result;2437}24382439static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)2440{2441gint intval = 0;2442(*fp_g_object_get)(settings, key, &intval, NULL);2443return create_Integer(env, intval);2444}24452446static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key)2447{2448gint intval = 0;2449(*fp_g_object_get)(settings, key, &intval, NULL);2450return create_Boolean(env, intval);2451}24522453static jobject gtk2_get_setting(JNIEnv *env, Setting property)2454{2455GtkSettings* settings = (*fp_gtk_settings_get_default)();24562457switch (property)2458{2459case GTK_FONT_NAME:2460return get_string_property(env, settings, "gtk-font-name");2461case GTK_ICON_SIZES:2462return get_string_property(env, settings, "gtk-icon-sizes");2463case GTK_CURSOR_BLINK:2464return get_boolean_property(env, settings, "gtk-cursor-blink");2465case GTK_CURSOR_BLINK_TIME:2466return get_integer_property(env, settings, "gtk-cursor-blink-time");2467}24682469return NULL;2470}24712472static gboolean gtk2_get_drawable_data(JNIEnv *env, jintArray pixelArray, jint x,2473jint y, jint width, jint height, jint jwidth, int dx, int dy, jint scale) {2474GdkPixbuf *pixbuf;2475jint *ary;24762477GdkWindow *root = (*fp_gdk_get_default_root_window)();24782479pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, x, y,24800, 0, width, height);2481if (pixbuf && scale != 1) {2482GdkPixbuf *scaledPixbuf;2483x /= scale;2484y /= scale;2485width /= scale;2486height /= scale;2487dx /= scale;2488dy /= scale;2489scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,2490GDK_INTERP_BILINEAR);2491(*fp_g_object_unref)(pixbuf);2492pixbuf = scaledPixbuf;2493}24942495if (pixbuf) {2496int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);2497int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);24982499if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width2500&& (*fp_gdk_pixbuf_get_height)(pixbuf) == height2501&& (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 82502&& (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB2503&& nchan >= 32504) {2505guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);25062507ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);2508if (ary) {2509jint _x, _y;2510int index;2511for (_y = 0; _y < height; _y++) {2512for (_x = 0; _x < width; _x++) {2513p = pix + (intptr_t) _y * stride + _x * nchan;25142515index = (_y + dy) * jwidth + (_x + dx);2516ary[index] = 0xff0000002517| (p[0] << 16)2518| (p[1] << 8)2519| (p[2]);25202521}2522}2523(*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);2524}2525}2526(*fp_g_object_unref)(pixbuf);2527}2528return JNI_FALSE;2529}25302531static GdkWindow* gtk2_get_window(void *widget) {2532return ((GtkWidget*)widget)->window;2533}25342535void gtk2_init(GtkApi* gtk) {2536gtk->version = GTK_2;25372538gtk->show_uri_load = >k2_show_uri_load;2539gtk->unload = >k2_unload;2540gtk->flush_event_loop = &flush_gtk_event_loop;2541gtk->gtk_check_version = fp_gtk_check_version;2542gtk->get_setting = >k2_get_setting;25432544gtk->paint_arrow = >k2_paint_arrow;2545gtk->paint_box = >k2_paint_box;2546gtk->paint_box_gap = >k2_paint_box_gap;2547gtk->paint_expander = >k2_paint_expander;2548gtk->paint_extension = >k2_paint_extension;2549gtk->paint_flat_box = >k2_paint_flat_box;2550gtk->paint_focus = >k2_paint_focus;2551gtk->paint_handle = >k2_paint_handle;2552gtk->paint_hline = >k2_paint_hline;2553gtk->paint_vline = >k2_paint_vline;2554gtk->paint_option = >k2_paint_option;2555gtk->paint_shadow = >k2_paint_shadow;2556gtk->paint_slider = >k2_paint_slider;2557gtk->paint_background = >k_paint_background;2558gtk->paint_check = >k2_paint_check;2559gtk->set_range_value = >k2_set_range_value;25602561gtk->init_painting = >k2_init_painting;2562gtk->copy_image = >k2_copy_image;25632564gtk->get_xthickness = >k2_get_xthickness;2565gtk->get_ythickness = >k2_get_ythickness;2566gtk->get_color_for_state = >k2_get_color_for_state;2567gtk->get_class_value = >k2_get_class_value;25682569gtk->get_pango_font_name = >k2_get_pango_font_name;2570gtk->get_icon_data = >k2_get_icon_data;2571gtk->get_file_icon_data = >k2_get_file_icon_data;2572gtk->gdk_threads_enter = fp_gdk_threads_enter;2573gtk->gdk_threads_leave = fp_gdk_threads_leave;2574gtk->gtk_show_uri = fp_gtk_show_uri;2575gtk->get_drawable_data = >k2_get_drawable_data;2576gtk->g_free = fp_g_free;25772578gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename;2579gtk->gtk_widget_hide = fp_gtk_widget_hide;2580gtk->gtk_main_quit = fp_gtk_main_quit;2581gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new;2582gtk->gtk_file_chooser_set_current_folder =2583fp_gtk_file_chooser_set_current_folder;2584gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename;2585gtk->gtk_file_chooser_set_current_name =2586fp_gtk_file_chooser_set_current_name;2587gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom;2588gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter;2589gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type;2590gtk->gtk_file_filter_new = fp_gtk_file_filter_new;2591gtk->gtk_file_chooser_set_do_overwrite_confirmation =2592fp_gtk_file_chooser_set_do_overwrite_confirmation;2593gtk->gtk_file_chooser_set_select_multiple =2594fp_gtk_file_chooser_set_select_multiple;2595gtk->gtk_file_chooser_get_current_folder =2596fp_gtk_file_chooser_get_current_folder;2597gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames;2598gtk->gtk_g_slist_length = fp_gtk_g_slist_length;2599gtk->g_signal_connect_data = fp_g_signal_connect_data;2600gtk->gtk_widget_show = fp_gtk_widget_show;2601gtk->gtk_main = fp_gtk_main;2602gtk->gtk_main_level = fp_gtk_main_level;2603gtk->g_path_get_dirname = fp_g_path_get_dirname;2604gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid;2605gtk->gtk_widget_destroy = fp_gtk_widget_destroy;2606gtk->gtk_window_present = fp_gtk_window_present;2607gtk->gtk_window_move = fp_gtk_window_move;2608gtk->gtk_window_resize = fp_gtk_window_resize;2609gtk->get_window = >k2_get_window;26102611gtk->g_object_unref = fp_g_object_unref;2612gtk->g_list_append = fp_g_list_append;2613gtk->g_list_free = fp_g_list_free;2614gtk->g_list_free_full = fp_g_list_free_full;2615}261626172618