Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/awt/gtk3_interface.c
32287 views
/*1* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24#include <dlfcn.h>25#include <setjmp.h>26#include <X11/Xlib.h>27#include <limits.h>28#include <string.h>29#include "gtk3_interface.h"30#include "java_awt_Transparency.h"31#include "sizecalc.h"32#include <jni_util.h>33#include <stdio.h>34#include "awt.h"3536static void *gtk3_libhandle = NULL;37static void *gthread_libhandle = NULL;3839static jmp_buf j;4041/* Widgets */42static GtkWidget *gtk3_widget = NULL;43static GtkWidget *gtk3_window = NULL;44static GtkFixed *gtk3_fixed = NULL;45static GtkStyleProvider *gtk3_css = NULL;4647/* Paint system */48static cairo_surface_t *surface = NULL;49static cairo_t *cr = NULL;5051static const char ENV_PREFIX[] = "GTK_MODULES=";5253static GtkWidget *gtk3_widgets[_GTK_WIDGET_TYPE_SIZE];5455static void throw_exception(JNIEnv *env, const char* name, const char* message)56{57jclass class = (*env)->FindClass(env, name);5859if (class != NULL)60(*env)->ThrowNew(env, class, message);6162(*env)->DeleteLocalRef(env, class);63}6465static void gtk3_add_state(GtkWidget *widget, GtkStateType state) {66GtkStateType old_state = fp_gtk_widget_get_state(widget);67fp_gtk_widget_set_state(widget, old_state | state);68}6970static void gtk3_remove_state(GtkWidget *widget, GtkStateType state) {71GtkStateType old_state = fp_gtk_widget_get_state(widget);72fp_gtk_widget_set_state(widget, old_state & ~state);73}7475/* This is a workaround for the bug:76* http://sourceware.org/bugzilla/show_bug.cgi?id=181477* (dlsym/dlopen clears dlerror state)78* This bug is specific to Linux, but there is no harm in79* applying this workaround on Solaris as well.80*/81static void* dl_symbol(const char* name)82{83void* result = dlsym(gtk3_libhandle, name);84if (!result)85longjmp(j, NO_SYMBOL_EXCEPTION);8687return result;88}8990static void* dl_symbol_gthread(const char* name)91{92void* result = dlsym(gthread_libhandle, name);93if (!result)94longjmp(j, NO_SYMBOL_EXCEPTION);9596return result;97}9899gboolean gtk3_check(const char* lib_name, gboolean load)100{101if (gtk3_libhandle != NULL) {102/* We've already successfully opened the GTK libs, so return true. */103return TRUE;104} else {105#ifdef RTLD_NOLOAD106void *lib = dlopen(lib_name, RTLD_LAZY | RTLD_NOLOAD);107if (!load || lib != NULL) {108return lib != NULL;109}110#else111#ifdef _AIX112/* On AIX we could implement this with the help of loadquery(L_GETINFO, ..) */113/* (see reload_table() in hotspot/src/os/aix/vm/loadlib_aix.cpp) but it is */114/* probably not worth it because most AIX servers don't have GTK libs anyway */115#endif116#endif117return dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL) != NULL;118}119}120121#define ADD_SUPPORTED_ACTION(actionStr) \122do { \123jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, \124"Ljava/awt/Desktop$Action;"); \125if (!(*env)->ExceptionCheck(env)) { \126jobject action = (*env)->GetStaticObjectField(env, cls_action, \127fld_action); \128(*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, \129action); \130} else { \131(*env)->ExceptionClear(env); \132} \133} while(0);134135136static void update_supported_actions(JNIEnv *env) {137GVfs * (*fp_g_vfs_get_default) (void);138const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);139const gchar * const * schemes = NULL;140141jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action");142CHECK_NULL(cls_action);143jclass cls_xDesktopPeer = (*env)->144FindClass(env, "sun/awt/X11/XDesktopPeer");145CHECK_NULL(cls_xDesktopPeer);146jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env,147cls_xDesktopPeer, "supportedActions", "Ljava/util/List;");148CHECK_NULL(fld_supportedActions);149jobject supportedActions = (*env)->GetStaticObjectField(env,150cls_xDesktopPeer, fld_supportedActions);151152jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList");153CHECK_NULL(cls_arrayList);154jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add",155"(Ljava/lang/Object;)Z");156CHECK_NULL(mid_arrayListAdd);157jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList,158"clear", "()V");159CHECK_NULL(mid_arrayListClear);160161(*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear);162163ADD_SUPPORTED_ACTION("OPEN");164165/**166* gtk_show_uri() documentation says:167*168* > you need to install gvfs to get support for uri schemes such as http://169* > or ftp://, as only local files are handled by GIO itself.170*171* So OPEN action was safely added here.172* However, it looks like Solaris 11 have gvfs support only for 32-bit173* applications only by default.174*/175176fp_g_vfs_get_default = dl_symbol("g_vfs_get_default");177fp_g_vfs_get_supported_uri_schemes =178dl_symbol("g_vfs_get_supported_uri_schemes");179dlerror();180181if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) {182GVfs * vfs = fp_g_vfs_get_default();183schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL;184if (schemes) {185int i = 0;186while (schemes[i]) {187if (strcmp(schemes[i], "http") == 0) {188ADD_SUPPORTED_ACTION("BROWSE");189ADD_SUPPORTED_ACTION("MAIL");190break;191}192i++;193}194}195} else {196#ifdef DEBUG197fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n");198#endif /* DEBUG */199}200201}202/**203* Functions for awt_Desktop.c204*/205static gboolean gtk3_show_uri_load(JNIEnv *env) {206gboolean success = FALSE;207dlerror();208fp_gtk_show_uri = dl_symbol("gtk_show_uri");209const char *dlsym_error = dlerror();210if (dlsym_error) {211#ifdef DEBUG212fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error);213#endif /* DEBUG */214} else if (fp_gtk_show_uri == NULL) {215#ifdef DEBUG216fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");217#endif /* DEBUG */218} else {219gtk->gtk_show_uri = fp_gtk_show_uri;220update_supported_actions(env);221success = TRUE;222}223return success;224}225226/**227* Functions for sun_awt_X11_GtkFileDialogPeer.c228*/229static void gtk3_file_chooser_load()230{231fp_gtk_file_chooser_get_filename = dl_symbol(232"gtk_file_chooser_get_filename");233fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new");234fp_gtk_file_chooser_set_current_folder = dl_symbol(235"gtk_file_chooser_set_current_folder");236fp_gtk_file_chooser_set_filename = dl_symbol(237"gtk_file_chooser_set_filename");238fp_gtk_file_chooser_set_current_name = dl_symbol(239"gtk_file_chooser_set_current_name");240fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom");241fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");242fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");243fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");244fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(245"gtk_file_chooser_set_do_overwrite_confirmation");246fp_gtk_file_chooser_set_select_multiple = dl_symbol(247"gtk_file_chooser_set_select_multiple");248fp_gtk_file_chooser_get_current_folder = dl_symbol(249"gtk_file_chooser_get_current_folder");250fp_gtk_file_chooser_get_filenames = dl_symbol(251"gtk_file_chooser_get_filenames");252fp_gtk_g_slist_length = dl_symbol("g_slist_length");253fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_window_get_xid");254}255256static void empty() {}257258static gboolean gtk3_version_3_10 = TRUE;259static gboolean gtk3_version_3_14 = FALSE;260static gboolean gtk3_version_3_20 = FALSE;261262GtkApi* gtk3_load(JNIEnv *env, const char* lib_name)263{264gboolean result;265int i;266int (*handler)();267int (*io_handler)();268char *gtk_modules_env;269gtk3_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);270if (gtk3_libhandle == NULL) {271return FALSE;272}273274gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);275if (gthread_libhandle == NULL) {276gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL);277if (gthread_libhandle == NULL)278return FALSE;279}280281if (setjmp(j) == 0)282{283fp_gtk_check_version = dl_symbol("gtk_check_version");284285/* GLib */286fp_glib_check_version = dlsym(gtk3_libhandle, "glib_check_version");287if (!fp_glib_check_version) {288dlerror();289}290fp_g_free = dl_symbol("g_free");291fp_g_object_unref = dl_symbol("g_object_unref");292293fp_g_main_context_iteration =294dl_symbol("g_main_context_iteration");295296fp_g_value_init = dl_symbol("g_value_init");297fp_g_type_is_a = dl_symbol("g_type_is_a");298fp_g_value_get_boolean = dl_symbol("g_value_get_boolean");299fp_g_value_get_char = dl_symbol("g_value_get_char");300fp_g_value_get_uchar = dl_symbol("g_value_get_uchar");301fp_g_value_get_int = dl_symbol("g_value_get_int");302fp_g_value_get_uint = dl_symbol("g_value_get_uint");303fp_g_value_get_long = dl_symbol("g_value_get_long");304fp_g_value_get_ulong = dl_symbol("g_value_get_ulong");305fp_g_value_get_int64 = dl_symbol("g_value_get_int64");306fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64");307fp_g_value_get_float = dl_symbol("g_value_get_float");308fp_g_value_get_double = dl_symbol("g_value_get_double");309fp_g_value_get_string = dl_symbol("g_value_get_string");310fp_g_value_get_enum = dl_symbol("g_value_get_enum");311fp_g_value_get_flags = dl_symbol("g_value_get_flags");312fp_g_value_get_param = dl_symbol("g_value_get_param");313fp_g_value_get_boxed = dl_symbol("g_value_get_boxed");314fp_g_value_get_pointer = dl_symbol("g_value_get_pointer");315316fp_g_object_get = dl_symbol("g_object_get");317fp_g_object_set = dl_symbol("g_object_set");318319fp_g_str_has_prefix = dl_symbol("g_str_has_prefix");320fp_g_strsplit = dl_symbol("g_strsplit");321fp_g_strfreev = dl_symbol("g_strfreev");322323/* GDK */324fp_gdk_get_default_root_window =325dl_symbol("gdk_get_default_root_window");326327/* Pixbuf */328fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new");329fp_gdk_pixbuf_new_from_file =330dl_symbol("gdk_pixbuf_new_from_file");331fp_gdk_pixbuf_get_from_drawable =332dl_symbol("gdk_pixbuf_get_from_window");333fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width");334fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height");335fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels");336fp_gdk_pixbuf_get_rowstride =337dl_symbol("gdk_pixbuf_get_rowstride");338fp_gdk_pixbuf_get_has_alpha =339dl_symbol("gdk_pixbuf_get_has_alpha");340fp_gdk_pixbuf_get_bits_per_sample =341dl_symbol("gdk_pixbuf_get_bits_per_sample");342fp_gdk_pixbuf_get_n_channels =343dl_symbol("gdk_pixbuf_get_n_channels");344fp_gdk_pixbuf_get_colorspace =345dl_symbol("gdk_pixbuf_get_colorspace");346347fp_cairo_image_surface_create = dl_symbol("cairo_image_surface_create");348fp_cairo_surface_destroy = dl_symbol("cairo_surface_destroy");349fp_cairo_surface_status = dl_symbol("cairo_surface_status");350fp_cairo_create = dl_symbol("cairo_create");351fp_cairo_destroy = dl_symbol("cairo_destroy");352fp_cairo_status = dl_symbol("cairo_status");353fp_cairo_fill = dl_symbol("cairo_fill");354fp_cairo_rectangle = dl_symbol("cairo_rectangle");355fp_cairo_set_source_rgb = dl_symbol("cairo_set_source_rgb");356fp_cairo_set_source_rgba = dl_symbol("cairo_set_source_rgba");357fp_cairo_surface_flush = dl_symbol("cairo_surface_flush");358fp_cairo_paint = dl_symbol("cairo_paint");359fp_cairo_clip = dl_symbol("cairo_clip");360fp_cairo_image_surface_get_data =361dl_symbol("cairo_image_surface_get_data");362fp_cairo_image_surface_get_stride =363dl_symbol("cairo_image_surface_get_stride");364365fp_gdk_pixbuf_get_from_surface =366dl_symbol("gdk_pixbuf_get_from_surface");367368fp_gtk_widget_get_state = dl_symbol("gtk_widget_get_state");369fp_gtk_widget_set_state = dl_symbol("gtk_widget_set_state");370371fp_gtk_widget_is_focus = dl_symbol("gtk_widget_is_focus");372fp_gtk_widget_set_allocation = dl_symbol("gtk_widget_set_allocation");373fp_gtk_widget_get_parent = dl_symbol("gtk_widget_get_parent");374fp_gtk_widget_get_window = dl_symbol("gtk_widget_get_window");375376fp_gtk_widget_get_style_context =377dl_symbol("gtk_widget_get_style_context");378fp_gtk_style_context_get_color =379dl_symbol("gtk_style_context_get_color");380fp_gtk_style_context_get_background_color =381dl_symbol("gtk_style_context_get_background_color");382fp_gtk_widget_get_state_flags = dl_symbol("gtk_widget_get_state_flags");383fp_gtk_style_context_set_state =384dl_symbol("gtk_style_context_set_state");385fp_gtk_style_context_add_class =386dl_symbol("gtk_style_context_add_class");387fp_gtk_style_context_save = dl_symbol("gtk_style_context_save");388fp_gtk_style_context_restore = dl_symbol("gtk_style_context_restore");389fp_gtk_render_check = dl_symbol("gtk_render_check");390fp_gtk_render_option = dl_symbol("gtk_render_option");391fp_gtk_render_extension = dl_symbol("gtk_render_extension");392fp_gtk_render_expander = dl_symbol("gtk_render_expander");393fp_gtk_render_frame_gap = dl_symbol("gtk_render_frame_gap");394fp_gtk_render_line = dl_symbol("gtk_render_line");395fp_gtk_widget_render_icon_pixbuf =396dl_symbol("gtk_widget_render_icon_pixbuf");397if (fp_gtk_check_version(3, 10, 0)) {398gtk3_version_3_10 = FALSE;399} else {400fp_gdk_window_create_similar_image_surface =401dl_symbol("gdk_window_create_similar_image_surface");402}403gtk3_version_3_14 = !fp_gtk_check_version(3, 14, 0);404405if (!fp_gtk_check_version(3, 20, 0)) {406gtk3_version_3_20 = TRUE;407fp_gtk_widget_path_copy = dl_symbol("gtk_widget_path_copy");408fp_gtk_widget_path_new = dl_symbol("gtk_widget_path_new");409fp_gtk_widget_path_append_type = dl_symbol("gtk_widget_path_append_type");410fp_gtk_widget_path_iter_set_object_name = dl_symbol("gtk_widget_path_iter_set_object_name");411fp_gtk_style_context_set_path = dl_symbol("gtk_style_context_set_path");412fp_gtk_widget_path_unref = dl_symbol("gtk_widget_path_unref");413fp_gtk_style_context_get_path = dl_symbol("gtk_style_context_get_path");414fp_gtk_style_context_new = dl_symbol("gtk_style_context_new");415}416417fp_gdk_window_create_similar_surface =418dl_symbol("gdk_window_create_similar_surface");419fp_gtk_settings_get_for_screen =420dl_symbol("gtk_settings_get_for_screen");421fp_gtk_widget_get_screen = dl_symbol("gtk_widget_get_screen");422fp_gtk_css_provider_get_named = dl_symbol("gtk_css_provider_get_named");423fp_gtk_style_context_add_provider =424dl_symbol("gtk_style_context_add_provider");425fp_gtk_render_frame = dl_symbol("gtk_render_frame");426fp_gtk_render_focus = dl_symbol("gtk_render_focus");427fp_gtk_render_handle = dl_symbol("gtk_render_handle");428fp_gtk_render_arrow = dl_symbol("gtk_render_arrow");429430fp_gtk_style_context_get_property =431dl_symbol("gtk_style_context_get_property");432fp_gtk_scrolled_window_set_shadow_type =433dl_symbol("gtk_scrolled_window_set_shadow_type");434fp_gtk_render_slider = dl_symbol("gtk_render_slider");435fp_gtk_style_context_get_padding =436dl_symbol("gtk_style_context_get_padding");437fp_gtk_range_set_inverted = dl_symbol("gtk_range_set_inverted");438fp_gtk_style_context_get_font = dl_symbol("gtk_style_context_get_font");439fp_gtk_widget_get_allocated_width =440dl_symbol("gtk_widget_get_allocated_width");441fp_gtk_widget_get_allocated_height =442dl_symbol("gtk_widget_get_allocated_height");443fp_gtk_icon_theme_get_default = dl_symbol("gtk_icon_theme_get_default");444fp_gtk_icon_theme_load_icon = dl_symbol("gtk_icon_theme_load_icon");445446fp_gtk_adjustment_set_lower = dl_symbol("gtk_adjustment_set_lower");447fp_gtk_adjustment_set_page_increment =448dl_symbol("gtk_adjustment_set_page_increment");449fp_gtk_adjustment_set_page_size =450dl_symbol("gtk_adjustment_set_page_size");451fp_gtk_adjustment_set_step_increment =452dl_symbol("gtk_adjustment_set_step_increment");453fp_gtk_adjustment_set_upper = dl_symbol("gtk_adjustment_set_upper");454fp_gtk_adjustment_set_value = dl_symbol("gtk_adjustment_set_value");455456fp_gtk_render_activity = dl_symbol("gtk_render_activity");457fp_gtk_render_background = dl_symbol("gtk_render_background");458fp_gtk_style_context_has_class =459dl_symbol("gtk_style_context_has_class");460461fp_gtk_style_context_set_junction_sides =462dl_symbol("gtk_style_context_set_junction_sides");463fp_gtk_style_context_add_region =464dl_symbol("gtk_style_context_add_region");465466fp_gtk_init_check = dl_symbol("gtk_init_check");467468/* GTK widgets */469fp_gtk_arrow_new = dl_symbol("gtk_arrow_new");470fp_gtk_button_new = dl_symbol("gtk_button_new");471fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new");472fp_gtk_check_button_new = dl_symbol("gtk_check_button_new");473fp_gtk_check_menu_item_new =474dl_symbol("gtk_check_menu_item_new");475fp_gtk_color_selection_dialog_new =476dl_symbol("gtk_color_selection_dialog_new");477fp_gtk_entry_new = dl_symbol("gtk_entry_new");478fp_gtk_fixed_new = dl_symbol("gtk_fixed_new");479fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new");480fp_gtk_image_new = dl_symbol("gtk_image_new");481fp_gtk_paned_new = dl_symbol("gtk_paned_new");482fp_gtk_scale_new = dl_symbol("gtk_scale_new");483fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new");484fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new");485fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new");486fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new");487fp_gtk_label_new = dl_symbol("gtk_label_new");488fp_gtk_menu_new = dl_symbol("gtk_menu_new");489fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new");490fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new");491fp_gtk_menu_item_set_submenu =492dl_symbol("gtk_menu_item_set_submenu");493fp_gtk_notebook_new = dl_symbol("gtk_notebook_new");494fp_gtk_progress_bar_new =495dl_symbol("gtk_progress_bar_new");496fp_gtk_progress_bar_set_orientation =497dl_symbol("gtk_orientable_set_orientation");498fp_gtk_radio_button_new =499dl_symbol("gtk_radio_button_new");500fp_gtk_radio_menu_item_new =501dl_symbol("gtk_radio_menu_item_new");502fp_gtk_scrolled_window_new =503dl_symbol("gtk_scrolled_window_new");504fp_gtk_separator_menu_item_new =505dl_symbol("gtk_separator_menu_item_new");506fp_gtk_text_view_new = dl_symbol("gtk_text_view_new");507fp_gtk_toggle_button_new =508dl_symbol("gtk_toggle_button_new");509fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new");510fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new");511fp_gtk_viewport_new = dl_symbol("gtk_viewport_new");512fp_gtk_window_new = dl_symbol("gtk_window_new");513fp_gtk_window_present = dl_symbol("gtk_window_present");514fp_gtk_window_move = dl_symbol("gtk_window_move");515fp_gtk_window_resize = dl_symbol("gtk_window_resize");516517fp_gtk_dialog_new = dl_symbol("gtk_dialog_new");518fp_gtk_frame_new = dl_symbol("gtk_frame_new");519520fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new");521fp_gtk_container_add = dl_symbol("gtk_container_add");522fp_gtk_menu_shell_append =523dl_symbol("gtk_menu_shell_append");524fp_gtk_widget_realize = dl_symbol("gtk_widget_realize");525fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy");526fp_gtk_widget_render_icon =527dl_symbol("gtk_widget_render_icon");528fp_gtk_widget_set_name =529dl_symbol("gtk_widget_set_name");530fp_gtk_widget_set_parent =531dl_symbol("gtk_widget_set_parent");532fp_gtk_widget_set_direction =533dl_symbol("gtk_widget_set_direction");534fp_gtk_widget_style_get =535dl_symbol("gtk_widget_style_get");536fp_gtk_widget_class_install_style_property =537dl_symbol("gtk_widget_class_install_style_property");538fp_gtk_widget_class_find_style_property =539dl_symbol("gtk_widget_class_find_style_property");540fp_gtk_widget_style_get_property =541dl_symbol("gtk_widget_style_get_property");542fp_pango_font_description_to_string =543dl_symbol("pango_font_description_to_string");544fp_gtk_settings_get_default =545dl_symbol("gtk_settings_get_default");546fp_gtk_widget_get_settings =547dl_symbol("gtk_widget_get_settings");548fp_gtk_border_get_type = dl_symbol("gtk_border_get_type");549fp_gtk_arrow_set = dl_symbol("gtk_arrow_set");550fp_gtk_widget_size_request =551dl_symbol("gtk_widget_size_request");552fp_gtk_range_get_adjustment =553dl_symbol("gtk_range_get_adjustment");554555fp_gtk_widget_hide = dl_symbol("gtk_widget_hide");556fp_gtk_main_quit = dl_symbol("gtk_main_quit");557fp_g_signal_connect_data = dl_symbol("g_signal_connect_data");558fp_gtk_widget_show = dl_symbol("gtk_widget_show");559fp_gtk_main = dl_symbol("gtk_main");560561fp_g_path_get_dirname = dl_symbol("g_path_get_dirname");562563fp_gdk_threads_init = dl_symbol("gdk_threads_init");564fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");565fp_gdk_threads_leave = dl_symbol("gdk_threads_leave");566567/**568* Functions for sun_awt_X11_GtkFileDialogPeer.c569*/570gtk3_file_chooser_load();571572fp_gtk_combo_box_new = dlsym(gtk3_libhandle, "gtk_combo_box_new");573fp_gtk_combo_box_entry_new = dlsym(gtk3_libhandle,574"gtk_combo_box_new_with_entry");575fp_gtk_separator_tool_item_new = dlsym(gtk3_libhandle,576"gtk_separator_tool_item_new");577fp_g_list_append = dl_symbol("g_list_append");578fp_g_list_free = dl_symbol("g_list_free");579fp_g_list_free_full = dl_symbol("g_list_free_full");580}581/* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION582* Otherwise we can check the return value of setjmp method.583*/584else585{586dlclose(gtk3_libhandle);587gtk3_libhandle = NULL;588589dlclose(gthread_libhandle);590gthread_libhandle = NULL;591592return NULL;593}594595/*596* Strip the AT-SPI GTK_MODULES if present597*/598gtk_modules_env = getenv ("GTK_MODULES");599if ((gtk_modules_env && strstr(gtk_modules_env, "atk-bridge")) ||600(gtk_modules_env && strstr(gtk_modules_env, "gail"))) {601/* careful, strtok modifies its args */602gchar *tmp_env = strdup(gtk_modules_env);603if (tmp_env) {604/* the new env will be smaller than the old one */605gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc,606sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env));607608if (new_env) {609strcpy(new_env, ENV_PREFIX);610611/* strip out 'atk-bridge' and 'gail' */612size_t PREFIX_LENGTH = strlen(ENV_PREFIX);613gchar *tmp_ptr = NULL;614for (s = strtok_r(tmp_env, ":", &tmp_ptr); s;615s = strtok_r(NULL, ":", &tmp_ptr)) {616if ((!strstr(s, "atk-bridge")) && (!strstr(s, "gail"))) {617if (strlen(new_env) > PREFIX_LENGTH) {618new_env = strcat(new_env, ":");619}620new_env = strcat(new_env, s);621}622}623if (putenv(new_env) != 0) {624/* no free() on success, putenv() doesn't copy string */625free(new_env);626}627}628free (tmp_env);629}630}631/*632* GTK should be initialized with gtk_init_check() before use.633*634* gtk_init_check installs its own error handlers. It is critical that635* we preserve error handler set from AWT. Otherwise we'll crash on636* BadMatch errors which we would normally ignore. The IO error handler637* is preserved here, too, just for consistency.638*/639AWT_LOCK();640handler = XSetErrorHandler(NULL);641io_handler = XSetIOErrorHandler(NULL);642643//According the GTK documentation, gdk_threads_init() should be644//called before gtk_init() or gtk_init_check()645fp_gdk_threads_init();646result = (*fp_gtk_init_check)(NULL, NULL);647648XSetErrorHandler(handler);649XSetIOErrorHandler(io_handler);650AWT_UNLOCK();651652/* Initialize widget array. */653for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)654{655gtk3_widgets[i] = NULL;656}657if (result) {658GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi));659gtk3_init(gtk);660return gtk;661}662return NULL;663}664665static int gtk3_unload()666{667int i;668char *gtk3_error;669670if (!gtk3_libhandle)671return TRUE;672673/* Release painting objects */674if (surface != NULL) {675fp_cairo_destroy(cr);676fp_cairo_surface_destroy(surface);677surface = NULL;678}679680if (gtk3_window != NULL) {681/* Destroying toplevel widget will destroy all contained widgets */682(*fp_gtk_widget_destroy)(gtk3_window);683684/* Unset some static data so they get reinitialized on next load */685gtk3_window = NULL;686}687688dlerror();689dlclose(gtk3_libhandle);690dlclose(gthread_libhandle);691if ((gtk3_error = dlerror()) != NULL)692{693return FALSE;694}695return TRUE;696}697698/* Dispatch all pending events from the GTK event loop.699* This is needed to catch theme change and update widgets' style.700*/701static void flush_gtk_event_loop()702{703while((*fp_g_main_context_iteration)(NULL));704}705706/*707* Initialize components of containment hierarchy. This creates a GtkFixed708* inside a GtkWindow. All widgets get realized.709*/710static void init_containers()711{712if (gtk3_window == NULL)713{714gtk3_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);715gtk3_fixed = (GtkFixed *)(*fp_gtk_fixed_new)();716(*fp_gtk_container_add)((GtkContainer*)gtk3_window,717(GtkWidget *)gtk3_fixed);718(*fp_gtk_widget_realize)(gtk3_window);719(*fp_gtk_widget_realize)((GtkWidget *)gtk3_fixed);720721GtkSettings* settings = fp_gtk_settings_get_for_screen(722fp_gtk_widget_get_screen(gtk3_window));723gchar* strval = NULL;724fp_g_object_get(settings, "gtk-theme-name", &strval, NULL);725gtk3_css = fp_gtk_css_provider_get_named(strval, NULL);726}727}728729/*730* Ensure everything is ready for drawing an element of the specified width731* and height.732*733* We should somehow handle translucent images. GTK can draw to X Drawables734* only, which don't support alpha. When we retrieve the image back from735* the server, translucency information is lost. There're several ways to736* work around this:737* 1) Subclass GdkPixmap and cache translucent objects on client side. This738* requires us to implement parts of X server drawing logic on client side.739* Many X requests can potentially be "translucent"; e.g. XDrawLine with740* fill=tile and a translucent tile is a "translucent" operation, whereas741* XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some742* do) intermix transparent and opaque operations which makes caching even743* more problematic.744* 2) Use Xorg 32bit ARGB visual when available. GDK has no native support745* for it (as of version 2.6). Also even in JDS 3 Xorg does not support746* these visuals by default, which makes optimizing for them pointless.747* We can consider doing this at a later point when ARGB visuals become more748* popular.749* 3') GTK has plans to use Cairo as its graphical backend (presumably in750* 2.8), and Cairo supports alpha. With it we could also get rid of the751* unnecessary round trip to server and do all the drawing on client side.752* 4) For now we draw to two different pixmaps and restore alpha channel by753* comparing results. This can be optimized by using subclassed pixmap and754*/755static void gtk3_init_painting(JNIEnv *env, gint width, gint height)756{757init_containers();758759if (cr) {760fp_cairo_destroy(cr);761}762763if (surface != NULL) {764/* free old stuff */765fp_cairo_surface_destroy(surface);766767}768769if (gtk3_version_3_10) {770surface = fp_gdk_window_create_similar_image_surface(771fp_gtk_widget_get_window(gtk3_window),772CAIRO_FORMAT_ARGB32, width, height, 1);773} else {774surface = fp_cairo_image_surface_create(CAIRO_FORMAT_ARGB32,775width, height);776}777778cr = fp_cairo_create(surface);779if (fp_cairo_surface_status(surface) || fp_cairo_status(cr)) {780JNU_ThrowOutOfMemoryError(env, "The surface size is too big");781}782}783784/*785* Restore image from white and black pixmaps and copy it into destination786* buffer. This method compares two pixbufs taken from white and black787* pixmaps and decodes color and alpha components. Pixbufs are RGB without788* alpha, destination buffer is ABGR.789*790* The return value is the transparency type of the resulting image, either791* one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and792* java_awt_Transparency_TRANSLUCENT.793*/794static gint gtk3_copy_image(gint *dst, gint width, gint height)795{796gint i, j, r, g, b;797guchar *data;798gint stride, padding;799800fp_cairo_surface_flush(surface);801data = (*fp_cairo_image_surface_get_data)(surface);802stride = (*fp_cairo_image_surface_get_stride)(surface);803padding = stride - width * 4;804if (stride > 0 && padding >= 0) {805for (i = 0; i < height; i++) {806for (j = 0; j < width; j++) {807int r = *data++;808int g = *data++;809int b = *data++;810int a = *data++;811*dst++ = (a << 24 | b << 16 | g << 8 | r);812}813data += padding;814}815}816return java_awt_Transparency_TRANSLUCENT;817}818819static void gtk3_set_direction(GtkWidget *widget, GtkTextDirection dir)820{821/*822* Some engines (inexplicably) look at the direction of the widget's823* parent, so we need to set the direction of both the widget and its824* parent.825*/826(*fp_gtk_widget_set_direction)(widget, dir);827GtkWidget* parent = fp_gtk_widget_get_parent(widget);828if (parent != NULL) {829fp_gtk_widget_set_direction(parent, dir);830}831}832833/* GTK state_type filter */834static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state)835{836GtkStateType result = GTK_STATE_NORMAL;837838if ((synth_state & DISABLED) != 0) {839result = GTK_STATE_INSENSITIVE;840} else if ((synth_state & PRESSED) != 0) {841result = GTK_STATE_ACTIVE;842} else if ((synth_state & MOUSE_OVER) != 0) {843result = GTK_STATE_PRELIGHT;844}845return result;846}847848static GtkStateFlags get_gtk_state_flags(gint synth_state)849{850GtkStateFlags flags = 0;851852if ((synth_state & DISABLED) != 0) {853flags |= GTK_STATE_FLAG_INSENSITIVE;854}855if (((synth_state & PRESSED) != 0 || (synth_state & SELECTED) != 0)) {856flags |= GTK_STATE_FLAG_ACTIVE;857}858if ((synth_state & MOUSE_OVER) != 0) {859flags |= GTK_STATE_FLAG_PRELIGHT;860}861if ((synth_state & FOCUSED) != 0) {862flags |= GTK_STATE_FLAG_FOCUSED;863}864return flags;865}866867static GtkStateFlags get_gtk_flags(GtkStateType state_type) {868GtkStateFlags flags = 0;869switch (state_type)870{871case GTK_STATE_PRELIGHT:872flags |= GTK_STATE_FLAG_PRELIGHT;873break;874case GTK_STATE_SELECTED:875flags |= GTK_STATE_FLAG_SELECTED;876break;877case GTK_STATE_INSENSITIVE:878flags |= GTK_STATE_FLAG_INSENSITIVE;879break;880case GTK_STATE_ACTIVE:881flags |= GTK_STATE_FLAG_ACTIVE;882break;883case GTK_STATE_FOCUSED:884flags |= GTK_STATE_FLAG_FOCUSED;885break;886default:887break;888}889return flags;890}891892/* GTK shadow_type filter */893static GtkShadowType get_gtk_shadow_type(WidgetType widget_type,894gint synth_state)895{896GtkShadowType result = GTK_SHADOW_OUT;897898if ((synth_state & SELECTED) != 0) {899result = GTK_SHADOW_IN;900}901return result;902}903904905static GtkWidget* gtk3_get_arrow(GtkArrowType arrow_type,906GtkShadowType shadow_type)907{908GtkWidget *arrow = NULL;909if (NULL == gtk3_widgets[_GTK_ARROW_TYPE])910{911gtk3_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type,912shadow_type);913(*fp_gtk_container_add)((GtkContainer *)gtk3_fixed,914gtk3_widgets[_GTK_ARROW_TYPE]);915(*fp_gtk_widget_realize)(gtk3_widgets[_GTK_ARROW_TYPE]);916}917arrow = gtk3_widgets[_GTK_ARROW_TYPE];918919(*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type);920return arrow;921}922923static GtkAdjustment* create_adjustment()924{925return (GtkAdjustment *)926(*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0);927}928929/**930* Returns a pointer to the cached native widget for the specified widget931* type.932*/933static GtkWidget *gtk3_get_widget(WidgetType widget_type)934{935gboolean init_result = FALSE;936GtkWidget *result = NULL;937switch (widget_type)938{939case BUTTON:940case TABLE_HEADER:941if (init_result = (NULL == gtk3_widgets[_GTK_BUTTON_TYPE]))942{943gtk3_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)();944}945result = gtk3_widgets[_GTK_BUTTON_TYPE];946break;947case CHECK_BOX:948if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_BUTTON_TYPE]))949{950gtk3_widgets[_GTK_CHECK_BUTTON_TYPE] =951(*fp_gtk_check_button_new)();952}953result = gtk3_widgets[_GTK_CHECK_BUTTON_TYPE];954break;955case CHECK_BOX_MENU_ITEM:956if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE]))957{958gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE] =959(*fp_gtk_check_menu_item_new)();960}961result = gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE];962break;963/************************************************************964* Creation a dedicated color chooser is dangerous because965* it deadlocks the EDT966************************************************************/967/* case COLOR_CHOOSER:968if (init_result =969(NULL == gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]))970{971gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] =972(*fp_gtk_color_selection_dialog_new)(NULL);973}974result = gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE];975break;*/976case COMBO_BOX:977if (init_result = (NULL == gtk3_widgets[_GTK_COMBO_BOX_TYPE]))978{979gtk3_widgets[_GTK_COMBO_BOX_TYPE] =980(*fp_gtk_combo_box_new)();981}982result = gtk3_widgets[_GTK_COMBO_BOX_TYPE];983break;984case COMBO_BOX_ARROW_BUTTON:985if (init_result =986(NULL == gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]))987{988gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] =989(*fp_gtk_toggle_button_new)();990}991result = gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE];992break;993case COMBO_BOX_TEXT_FIELD:994if (init_result =995(NULL == gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]))996{997result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] =998(*fp_gtk_entry_new)();999}1000result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE];1001break;1002case DESKTOP_ICON:1003case INTERNAL_FRAME_TITLE_PANE:1004case LABEL:1005if (init_result = (NULL == gtk3_widgets[_GTK_LABEL_TYPE]))1006{1007gtk3_widgets[_GTK_LABEL_TYPE] =1008(*fp_gtk_label_new)(NULL);1009}1010result = gtk3_widgets[_GTK_LABEL_TYPE];1011break;1012case DESKTOP_PANE:1013case PANEL:1014case ROOT_PANE:1015if (init_result = (NULL == gtk3_widgets[_GTK_CONTAINER_TYPE]))1016{1017/* There is no constructor for a container type. I've1018* chosen GtkFixed container since it has a default1019* constructor.1020*/1021gtk3_widgets[_GTK_CONTAINER_TYPE] =1022(*fp_gtk_fixed_new)();1023}1024result = gtk3_widgets[_GTK_CONTAINER_TYPE];1025break;1026case EDITOR_PANE:1027case TEXT_AREA:1028case TEXT_PANE:1029if (init_result = (NULL == gtk3_widgets[_GTK_TEXT_VIEW_TYPE]))1030{1031gtk3_widgets[_GTK_TEXT_VIEW_TYPE] =1032(*fp_gtk_text_view_new)();1033}1034result = gtk3_widgets[_GTK_TEXT_VIEW_TYPE];1035break;1036case FORMATTED_TEXT_FIELD:1037case PASSWORD_FIELD:1038case TEXT_FIELD:1039if (init_result = (NULL == gtk3_widgets[_GTK_ENTRY_TYPE]))1040{1041gtk3_widgets[_GTK_ENTRY_TYPE] =1042(*fp_gtk_entry_new)();1043}1044result = gtk3_widgets[_GTK_ENTRY_TYPE];1045break;1046case HANDLE_BOX:1047if (init_result = (NULL == gtk3_widgets[_GTK_HANDLE_BOX_TYPE]))1048{1049gtk3_widgets[_GTK_HANDLE_BOX_TYPE] =1050(*fp_gtk_handle_box_new)();1051}1052result = gtk3_widgets[_GTK_HANDLE_BOX_TYPE];1053break;1054case HSCROLL_BAR:1055case HSCROLL_BAR_BUTTON_LEFT:1056case HSCROLL_BAR_BUTTON_RIGHT:1057case HSCROLL_BAR_TRACK:1058case HSCROLL_BAR_THUMB:1059if (init_result = (NULL == gtk3_widgets[_GTK_HSCROLLBAR_TYPE]))1060{1061gtk3_widgets[_GTK_HSCROLLBAR_TYPE] =1062(*fp_gtk_hscrollbar_new)(create_adjustment());1063}1064result = gtk3_widgets[_GTK_HSCROLLBAR_TYPE];1065break;1066case HSEPARATOR:1067if (init_result = (NULL == gtk3_widgets[_GTK_HSEPARATOR_TYPE]))1068{1069gtk3_widgets[_GTK_HSEPARATOR_TYPE] =1070(*fp_gtk_hseparator_new)();1071}1072result = gtk3_widgets[_GTK_HSEPARATOR_TYPE];1073break;1074case HSLIDER:1075case HSLIDER_THUMB:1076case HSLIDER_TRACK:1077if (init_result = (NULL == gtk3_widgets[_GTK_HSCALE_TYPE]))1078{1079gtk3_widgets[_GTK_HSCALE_TYPE] =1080(*fp_gtk_scale_new)(GTK_ORIENTATION_HORIZONTAL, NULL);1081}1082result = gtk3_widgets[_GTK_HSCALE_TYPE];1083break;1084case HSPLIT_PANE_DIVIDER:1085case SPLIT_PANE:1086if (init_result = (NULL == gtk3_widgets[_GTK_HPANED_TYPE]))1087{1088gtk3_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_paned_new)(GTK_ORIENTATION_HORIZONTAL);1089}1090result = gtk3_widgets[_GTK_HPANED_TYPE];1091break;1092case IMAGE:1093if (init_result = (NULL == gtk3_widgets[_GTK_IMAGE_TYPE]))1094{1095gtk3_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)();1096}1097result = gtk3_widgets[_GTK_IMAGE_TYPE];1098break;1099case INTERNAL_FRAME:1100if (init_result = (NULL == gtk3_widgets[_GTK_WINDOW_TYPE]))1101{1102gtk3_widgets[_GTK_WINDOW_TYPE] =1103(*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);1104}1105result = gtk3_widgets[_GTK_WINDOW_TYPE];1106break;1107case TOOL_TIP:1108if (init_result = (NULL == gtk3_widgets[_GTK_TOOLTIP_TYPE]))1109{1110result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);1111gtk3_widgets[_GTK_TOOLTIP_TYPE] = result;1112}1113result = gtk3_widgets[_GTK_TOOLTIP_TYPE];1114break;1115case LIST:1116case TABLE:1117case TREE:1118case TREE_CELL:1119if (init_result = (NULL == gtk3_widgets[_GTK_TREE_VIEW_TYPE]))1120{1121gtk3_widgets[_GTK_TREE_VIEW_TYPE] =1122(*fp_gtk_tree_view_new)();1123}1124result = gtk3_widgets[_GTK_TREE_VIEW_TYPE];1125break;1126case TITLED_BORDER:1127if (init_result = (NULL == gtk3_widgets[_GTK_FRAME_TYPE]))1128{1129gtk3_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL);1130}1131result = gtk3_widgets[_GTK_FRAME_TYPE];1132break;1133case POPUP_MENU:1134if (init_result = (NULL == gtk3_widgets[_GTK_MENU_TYPE]))1135{1136gtk3_widgets[_GTK_MENU_TYPE] =1137(*fp_gtk_menu_new)();1138}1139result = gtk3_widgets[_GTK_MENU_TYPE];1140break;1141case MENU:1142case MENU_ITEM:1143case MENU_ITEM_ACCELERATOR:1144if (init_result = (NULL == gtk3_widgets[_GTK_MENU_ITEM_TYPE]))1145{1146gtk3_widgets[_GTK_MENU_ITEM_TYPE] =1147(*fp_gtk_menu_item_new)();1148}1149result = gtk3_widgets[_GTK_MENU_ITEM_TYPE];1150break;1151case MENU_BAR:1152if (init_result = (NULL == gtk3_widgets[_GTK_MENU_BAR_TYPE]))1153{1154gtk3_widgets[_GTK_MENU_BAR_TYPE] =1155(*fp_gtk_menu_bar_new)();1156}1157result = gtk3_widgets[_GTK_MENU_BAR_TYPE];1158break;1159case COLOR_CHOOSER:1160case OPTION_PANE:1161if (init_result = (NULL == gtk3_widgets[_GTK_DIALOG_TYPE]))1162{1163gtk3_widgets[_GTK_DIALOG_TYPE] =1164(*fp_gtk_dialog_new)();1165}1166result = gtk3_widgets[_GTK_DIALOG_TYPE];1167break;1168case POPUP_MENU_SEPARATOR:1169if (init_result =1170(NULL == gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]))1171{1172gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] =1173(*fp_gtk_separator_menu_item_new)();1174}1175result = gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE];1176break;1177case HPROGRESS_BAR:1178if (init_result = (NULL == gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE]))1179{1180gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE] =1181(*fp_gtk_progress_bar_new)();1182}1183result = gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE];1184break;1185case VPROGRESS_BAR:1186if (init_result = (NULL == gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE]))1187{1188gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE] =1189(*fp_gtk_progress_bar_new)();1190/*1191* Vertical JProgressBars always go bottom-to-top,1192* regardless of the ComponentOrientation.1193*/1194(*fp_gtk_progress_bar_set_orientation)(1195(GtkProgressBar *)gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE],1196GTK_PROGRESS_BOTTOM_TO_TOP);1197}1198result = gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE];1199break;1200case RADIO_BUTTON:1201if (init_result = (NULL == gtk3_widgets[_GTK_RADIO_BUTTON_TYPE]))1202{1203gtk3_widgets[_GTK_RADIO_BUTTON_TYPE] =1204(*fp_gtk_radio_button_new)(NULL);1205}1206result = gtk3_widgets[_GTK_RADIO_BUTTON_TYPE];1207break;1208case RADIO_BUTTON_MENU_ITEM:1209if (init_result =1210(NULL == gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE]))1211{1212gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE] =1213(*fp_gtk_radio_menu_item_new)(NULL);1214}1215result = gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE];1216break;1217case SCROLL_PANE:1218if (init_result =1219(NULL == gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE]))1220{1221gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE] =1222(*fp_gtk_scrolled_window_new)(NULL, NULL);1223}1224result = gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE];1225break;1226case SPINNER:1227case SPINNER_ARROW_BUTTON:1228case SPINNER_TEXT_FIELD:1229if (init_result = (NULL == gtk3_widgets[_GTK_SPIN_BUTTON_TYPE]))1230{1231result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE] =1232(*fp_gtk_spin_button_new)(NULL, 0, 0);1233}1234result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE];1235break;1236case TABBED_PANE:1237case TABBED_PANE_TAB_AREA:1238case TABBED_PANE_CONTENT:1239case TABBED_PANE_TAB:1240if (init_result = (NULL == gtk3_widgets[_GTK_NOTEBOOK_TYPE]))1241{1242gtk3_widgets[_GTK_NOTEBOOK_TYPE] =1243(*fp_gtk_notebook_new)(NULL);1244}1245result = gtk3_widgets[_GTK_NOTEBOOK_TYPE];1246break;1247case TOGGLE_BUTTON:1248if (init_result = (NULL == gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE]))1249{1250gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE] =1251(*fp_gtk_toggle_button_new)(NULL);1252}1253result = gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE];1254break;1255case TOOL_BAR:1256case TOOL_BAR_DRAG_WINDOW:1257if (init_result = (NULL == gtk3_widgets[_GTK_TOOLBAR_TYPE]))1258{1259gtk3_widgets[_GTK_TOOLBAR_TYPE] =1260(*fp_gtk_toolbar_new)(NULL);1261}1262result = gtk3_widgets[_GTK_TOOLBAR_TYPE];1263break;1264case TOOL_BAR_SEPARATOR:1265if (init_result =1266(NULL == gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]))1267{1268gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] =1269(*fp_gtk_separator_tool_item_new)();1270}1271result = gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE];1272break;1273case VIEWPORT:1274if (init_result = (NULL == gtk3_widgets[_GTK_VIEWPORT_TYPE]))1275{1276GtkAdjustment *adjustment = create_adjustment();1277gtk3_widgets[_GTK_VIEWPORT_TYPE] =1278(*fp_gtk_viewport_new)(adjustment, adjustment);1279}1280result = gtk3_widgets[_GTK_VIEWPORT_TYPE];1281break;1282case VSCROLL_BAR:1283case VSCROLL_BAR_BUTTON_UP:1284case VSCROLL_BAR_BUTTON_DOWN:1285case VSCROLL_BAR_TRACK:1286case VSCROLL_BAR_THUMB:1287if (init_result = (NULL == gtk3_widgets[_GTK_VSCROLLBAR_TYPE]))1288{1289gtk3_widgets[_GTK_VSCROLLBAR_TYPE] =1290(*fp_gtk_vscrollbar_new)(create_adjustment());1291}1292result = gtk3_widgets[_GTK_VSCROLLBAR_TYPE];1293break;1294case VSEPARATOR:1295if (init_result = (NULL == gtk3_widgets[_GTK_VSEPARATOR_TYPE]))1296{1297gtk3_widgets[_GTK_VSEPARATOR_TYPE] =1298(*fp_gtk_vseparator_new)();1299}1300result = gtk3_widgets[_GTK_VSEPARATOR_TYPE];1301break;1302case VSLIDER:1303case VSLIDER_THUMB:1304case VSLIDER_TRACK:1305if (init_result = (NULL == gtk3_widgets[_GTK_VSCALE_TYPE]))1306{1307gtk3_widgets[_GTK_VSCALE_TYPE] =1308(*fp_gtk_scale_new)(GTK_ORIENTATION_VERTICAL, NULL);1309}1310result = gtk3_widgets[_GTK_VSCALE_TYPE];1311/*1312* Vertical JSliders start at the bottom, while vertical1313* GtkVScale widgets start at the top (by default), so to fix1314* this we set the "inverted" flag to get the Swing behavior.1315*/1316fp_gtk_range_set_inverted((GtkRange*)result, TRUE);1317break;1318case VSPLIT_PANE_DIVIDER:1319if (init_result = (NULL == gtk3_widgets[_GTK_VPANED_TYPE]))1320{1321gtk3_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_paned_new)(GTK_ORIENTATION_VERTICAL);1322}1323result = gtk3_widgets[_GTK_VPANED_TYPE];1324break;1325default:1326result = NULL;1327break;1328}13291330if (result != NULL && init_result)1331{1332if (widget_type == RADIO_BUTTON_MENU_ITEM ||1333widget_type == CHECK_BOX_MENU_ITEM ||1334widget_type == MENU_ITEM ||1335widget_type == MENU ||1336widget_type == POPUP_MENU_SEPARATOR)1337{1338GtkWidget *menu = gtk3_get_widget(POPUP_MENU);1339(*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result);1340}1341else if (widget_type == POPUP_MENU)1342{1343GtkWidget *menu_bar = gtk3_get_widget(MENU_BAR);1344GtkWidget *root_menu = (*fp_gtk_menu_item_new)();1345(*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result);1346(*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu);1347}1348else if (widget_type == COMBO_BOX_TEXT_FIELD )1349{1350GtkWidget* combo = gtk3_get_widget(COMBO_BOX);13511352/*1353* We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry1354* in order to trick engines into thinking it's a real combobox1355* arrow button/text field.1356*/13571358fp_gtk_container_add ((GtkContainer*)(combo), result);1359GtkStyleContext* context = fp_gtk_widget_get_style_context (combo);1360fp_gtk_style_context_add_class (context, "combobox-entry");1361context = fp_gtk_widget_get_style_context (result);1362fp_gtk_style_context_add_class (context, "combobox");1363fp_gtk_style_context_add_class (context, "entry");1364}1365else if (widget_type == COMBO_BOX_ARROW_BUTTON )1366{1367GtkWidget* combo = gtk3_get_widget(COMBO_BOX);1368fp_gtk_widget_set_parent(result, combo);1369}1370else if (widget_type != TOOL_TIP &&1371widget_type != INTERNAL_FRAME &&1372widget_type != OPTION_PANE)1373{1374(*fp_gtk_container_add)((GtkContainer *)gtk3_fixed, result);1375}1376(*fp_gtk_widget_realize)(result);1377}1378return result;1379}13801381static void append_element (GtkWidgetPath *path, const gchar *selector)1382{1383fp_gtk_widget_path_append_type (path, G_TYPE_NONE);1384fp_gtk_widget_path_iter_set_object_name (path, -1, selector);1385}13861387static GtkWidgetPath* createWidgetPath(const GtkWidgetPath* path) {1388if (path == NULL) {1389return fp_gtk_widget_path_new();1390} else {1391return fp_gtk_widget_path_copy(path);1392}1393}13941395static GtkStyleContext* get_style(WidgetType widget_type, const gchar *detail)1396{1397if (!gtk3_version_3_20) {1398gtk3_widget = gtk3_get_widget(widget_type);1399GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);1400fp_gtk_style_context_save (context);1401if (detail != 0) {1402transform_detail_string(detail, context);1403}1404return context;1405} else {1406gtk3_widget = gtk3_get_widget(widget_type);1407GtkStyleContext* widget_context = fp_gtk_widget_get_style_context (gtk3_widget);1408GtkWidgetPath *path = NULL;1409if (detail != 0) {1410if (strcmp(detail, "checkbutton") == 0) {1411path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));1412append_element(path, "check");1413} else if (strcmp(detail, "radiobutton") == 0) {1414path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));1415append_element(path, "radio");1416} else if (strcmp(detail, "vscale") == 0 || strcmp(detail, "hscale") == 0) {1417path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));1418append_element(path, "slider");1419} else if (strcmp(detail, "trough") == 0) {1420//This is a fast solution to the scrollbar trough not being rendered properly1421if (widget_type == HSCROLL_BAR || widget_type == HSCROLL_BAR_TRACK ||1422widget_type == VSCROLL_BAR || widget_type == VSCROLL_BAR_TRACK) {1423path = createWidgetPath (NULL);1424} else {1425path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));1426}1427append_element(path, detail);1428} else if (strcmp(detail, "bar") == 0) {1429path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));1430append_element(path, "trough");1431append_element(path, "progress");1432} else if (strcmp(detail, "vscrollbar") == 0 || strcmp(detail, "hscrollbar") == 0) {1433path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));1434append_element(path, "button");1435} else if (strcmp(detail, "check") == 0) {1436path = createWidgetPath (NULL);1437append_element(path, detail);1438} else if (strcmp(detail, "option") == 0) {1439path = createWidgetPath (NULL);1440append_element(path, "radio");1441} else if (strcmp(detail, "paned") == 0) {1442path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));1443append_element(path, "paned");1444append_element(path, "separator");1445} else {1446path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));1447append_element(path, detail);1448}1449} else {1450path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));1451}14521453GtkStyleContext *context = fp_gtk_style_context_new ();1454fp_gtk_style_context_set_path (context, path);1455fp_gtk_widget_path_unref (path);1456return context;1457}1458}14591460static void disposeOrRestoreContext(GtkStyleContext *context)1461{1462if (!gtk3_version_3_20) {1463fp_gtk_style_context_restore (context);1464} else {1465fp_g_object_unref (context);1466}1467}14681469static void gtk3_paint_arrow(WidgetType widget_type, GtkStateType state_type,1470GtkShadowType shadow_type, const gchar *detail,1471gint x, gint y, gint width, gint height,1472GtkArrowType arrow_type, gboolean fill)1473{1474gdouble xx, yy, a = G_PI;1475int s = width;1476gtk3_widget = gtk3_get_arrow(arrow_type, shadow_type);14771478switch (widget_type)1479{1480case SPINNER_ARROW_BUTTON:1481s = (int)(0.4 * width + 0.5) + 1;1482if (arrow_type == GTK_ARROW_UP) {1483a = 0;1484} else if (arrow_type == GTK_ARROW_DOWN) {1485a = G_PI;1486}1487break;14881489case HSCROLL_BAR_BUTTON_LEFT:1490s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1;1491a = 3 * G_PI / 2;1492break;14931494case HSCROLL_BAR_BUTTON_RIGHT:1495s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1;1496a = G_PI / 2;1497break;14981499case VSCROLL_BAR_BUTTON_UP:1500s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1;1501a = 0;1502break;15031504case VSCROLL_BAR_BUTTON_DOWN:1505s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1;1506a = G_PI;1507break;15081509case COMBO_BOX_ARROW_BUTTON:1510s = (int)(0.3 * height + 0.5) + 1;1511a = G_PI;1512break;15131514case TABLE:1515s = (int)(0.8 * height + 0.5) + 1;1516if (arrow_type == GTK_ARROW_UP) {1517a = G_PI;1518} else if (arrow_type == GTK_ARROW_DOWN) {1519a = 0;1520}1521break;15221523case MENU_ITEM:1524if (arrow_type == GTK_ARROW_UP) {1525a = G_PI;1526} else if (arrow_type == GTK_ARROW_DOWN) {1527a = 0;1528} else if (arrow_type == GTK_ARROW_RIGHT) {1529a = G_PI / 2;1530} else if (arrow_type == GTK_ARROW_LEFT) {1531a = 3 * G_PI / 2;1532}1533break;15341535default:1536if (arrow_type == GTK_ARROW_UP) {1537a = G_PI;1538} else if (arrow_type == GTK_ARROW_DOWN) {1539a = 0;1540} else if (arrow_type == GTK_ARROW_RIGHT) {1541a = G_PI / 2;1542} else if (arrow_type == GTK_ARROW_LEFT) {1543a = 3 * G_PI / 2;1544}1545break;1546}15471548if (s < width && s < height) {1549xx = x + (0.5 * (width - s) + 0.5);1550yy = y + (0.5 * (height - s) + 0.5);1551} else {1552xx = x;1553yy = y;1554}15551556GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);1557fp_gtk_style_context_save (context);155815591560if (detail != NULL) {1561transform_detail_string(detail, context);1562}15631564GtkStateFlags flags = get_gtk_flags(state_type);15651566fp_gtk_style_context_set_state (context, flags);15671568(*fp_gtk_render_arrow)(context, cr, a, xx, yy, s);15691570fp_gtk_style_context_restore (context);1571}15721573static void gtk3_paint_box(WidgetType widget_type, GtkStateType state_type,1574GtkShadowType shadow_type, const gchar *detail,1575gint x, gint y, gint width, gint height,1576gint synth_state, GtkTextDirection dir)1577{1578gtk3_widget = gtk3_get_widget(widget_type);15791580if (widget_type == HSLIDER_TRACK) {1581/*1582* For horizontal JSliders with right-to-left orientation, we need1583* to set the "inverted" flag to match the native GTK behavior where1584* the foreground highlight is on the right side of the slider thumb.1585* This is needed especially for the ubuntulooks engine, which looks1586* exclusively at the "inverted" flag to determine on which side of1587* the thumb to paint the highlight...1588*/1589fp_gtk_range_set_inverted((GtkRange*)gtk3_widget, dir ==1590GTK_TEXT_DIR_RTL);15911592/*1593* Note however that other engines like clearlooks will look at both1594* the "inverted" field and the text direction to determine how1595* the foreground highlight is painted:1596* !inverted && ltr --> paint highlight on left side1597* !inverted && rtl --> paint highlight on right side1598* inverted && ltr --> paint highlight on right side1599* inverted && rtl --> paint highlight on left side1600* So the only way to reliably get the desired results for horizontal1601* JSlider (i.e., highlight on left side for LTR ComponentOrientation1602* and highlight on right side for RTL ComponentOrientation) is to1603* always override text direction as LTR, and then set the "inverted"1604* flag accordingly (as we have done above).1605*/1606dir = GTK_TEXT_DIR_LTR;1607}16081609/*1610* Some engines (e.g. clearlooks) will paint the shadow of certain1611* widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the1612* the text direction.1613*/1614gtk3_set_direction(gtk3_widget, dir);16151616GtkStyleContext* context = get_style(widget_type, detail);16171618GtkStateFlags flags = get_gtk_flags(state_type);1619if (shadow_type == GTK_SHADOW_IN && widget_type != COMBO_BOX_ARROW_BUTTON) {1620flags |= GTK_STATE_FLAG_ACTIVE;1621}16221623if (synth_state & MOUSE_OVER) {1624flags |= GTK_STATE_FLAG_PRELIGHT;1625}16261627if (synth_state & FOCUSED) {1628flags |= GTK_STATE_FLAG_FOCUSED;1629}16301631if (synth_state & DEFAULT) {1632fp_gtk_style_context_add_class (context, "default");1633}16341635if (fp_gtk_style_context_has_class(context, "trough")) {1636flags |= GTK_STATE_FLAG_BACKDROP;1637}16381639fp_gtk_style_context_set_state (context, flags);16401641fp_gtk_render_background (context, cr, x, y, width, height);1642if (shadow_type != GTK_SHADOW_NONE) {1643fp_gtk_render_frame(context, cr, x, y, width, height);1644}16451646disposeOrRestoreContext(context);16471648/*1649* Reset the text direction to the default value so that we don't1650* accidentally affect other operations and widgets.1651*/1652gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR);16531654//This is a fast solution to the scrollbar trough not being rendered properly1655if ((widget_type == HSCROLL_BAR || widget_type == HSCROLL_BAR_TRACK ||1656widget_type == VSCROLL_BAR || widget_type == VSCROLL_BAR_TRACK) && detail != 0) {1657gtk3_paint_box(widget_type, state_type, shadow_type, NULL,1658x, y, width, height, synth_state, dir);1659}1660}16611662static void gtk3_paint_box_gap(WidgetType widget_type, GtkStateType state_type,1663GtkShadowType shadow_type, const gchar *detail,1664gint x, gint y, gint width, gint height,1665GtkPositionType gap_side, gint gap_x, gint gap_width)1666{1667gtk3_widget = gtk3_get_widget(widget_type);16681669GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);16701671fp_gtk_style_context_save (context);16721673GtkStateFlags flags = get_gtk_flags(state_type);1674fp_gtk_style_context_set_state(context, flags);16751676if (detail != 0) {1677transform_detail_string(detail, context);1678}1679fp_gtk_render_background(context, cr, x, y, width, height);16801681if (shadow_type != GTK_SHADOW_NONE) {1682fp_gtk_render_frame_gap(context, cr, x, y, width, height, gap_side,1683(gdouble)gap_x, (gdouble)gap_x + gap_width);1684}1685fp_gtk_style_context_restore (context);1686}16871688static void gtk3_paint_check(WidgetType widget_type, gint synth_state,1689const gchar *detail, gint x, gint y, gint width, gint height)1690{1691GtkStyleContext* context = get_style(widget_type, detail);16921693GtkStateFlags flags = get_gtk_state_flags(synth_state);1694if (gtk3_version_3_14 && (synth_state & SELECTED)) {1695flags &= ~GTK_STATE_FLAG_SELECTED;1696flags |= GTK_STATE_FLAG_CHECKED;1697}1698fp_gtk_style_context_set_state(context, flags);16991700fp_gtk_render_background(context, cr, x, y, width, height);1701fp_gtk_render_frame(context, cr, x, y, width, height);1702fp_gtk_render_check(context, cr, x, y, width, height);1703disposeOrRestoreContext(context);1704}170517061707static void gtk3_paint_expander(WidgetType widget_type, GtkStateType state_type,1708const gchar *detail, gint x, gint y, gint width, gint height,1709GtkExpanderStyle expander_style)1710{1711gtk3_widget = gtk3_get_widget(widget_type);17121713GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);17141715fp_gtk_style_context_save (context);17161717GtkStateFlags flags = get_gtk_flags(state_type);1718if (expander_style == GTK_EXPANDER_EXPANDED) {1719if (gtk3_version_3_14) {1720flags |= GTK_STATE_FLAG_CHECKED;1721} else {1722flags |= GTK_STATE_FLAG_ACTIVE;1723}1724}17251726fp_gtk_style_context_set_state(context, flags);17271728if (detail != 0) {1729transform_detail_string(detail, context);1730}17311732fp_gtk_render_expander (context, cr, x + 2, y + 2, width - 4, height - 4);17331734fp_gtk_style_context_restore (context);1735}17361737static void gtk3_paint_extension(WidgetType widget_type, GtkStateType state_type,1738GtkShadowType shadow_type, const gchar *detail,1739gint x, gint y, gint width, gint height, GtkPositionType gap_side)1740{1741gtk3_widget = gtk3_get_widget(widget_type);17421743GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);17441745fp_gtk_style_context_save (context);17461747GtkStateFlags flags = GTK_STATE_FLAG_NORMAL;17481749if (state_type == 0) {1750flags = GTK_STATE_FLAG_ACTIVE;1751}17521753fp_gtk_style_context_set_state(context, flags);17541755if (detail != 0) {1756transform_detail_string(detail, context);1757}1758switch(gap_side) {1759case GTK_POS_LEFT:1760fp_gtk_style_context_add_class(context, "right");1761break;1762case GTK_POS_RIGHT:1763fp_gtk_style_context_add_class(context, "left");1764break;1765case GTK_POS_TOP:1766fp_gtk_style_context_add_class(context, "bottom");1767break;1768case GTK_POS_BOTTOM:1769fp_gtk_style_context_add_class(context, "top");1770break;1771default:1772break;1773}17741775fp_gtk_render_extension(context, cr, x, y, width, height, gap_side);17761777fp_gtk_style_context_restore (context);1778}17791780static void gtk3_paint_flat_box(WidgetType widget_type, GtkStateType state_type,1781GtkShadowType shadow_type, const gchar *detail,1782gint x, gint y, gint width, gint height, gboolean has_focus)1783{1784if (state_type == GTK_STATE_PRELIGHT &&1785(widget_type == CHECK_BOX || widget_type == RADIO_BUTTON)) {1786return;1787}17881789GtkStyleContext* context = NULL;1790if (widget_type == TOOL_TIP) {1791context = get_style(widget_type, detail);1792fp_gtk_style_context_add_class(context, "background");1793} else {1794gtk3_widget = gtk3_get_widget(widget_type);1795context = fp_gtk_widget_get_style_context (gtk3_widget);1796fp_gtk_style_context_save (context);1797if (detail != 0) {1798transform_detail_string(detail, context);1799}1800}18011802GtkStateFlags flags = get_gtk_flags(state_type);18031804if (has_focus) {1805flags |= GTK_STATE_FLAG_FOCUSED;1806}18071808fp_gtk_style_context_set_state (context, flags);18091810if (widget_type == COMBO_BOX_TEXT_FIELD) {1811width += height /2;1812}18131814fp_gtk_render_background (context, cr, x, y, width, height);1815if (widget_type == TOOL_TIP) {1816disposeOrRestoreContext(context);1817} else {1818fp_gtk_style_context_restore (context);1819}1820}18211822static void gtk3_paint_focus(WidgetType widget_type, GtkStateType state_type,1823const char *detail, gint x, gint y, gint width, gint height)1824{1825gtk3_widget = gtk3_get_widget(widget_type);18261827GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);1828fp_gtk_style_context_save (context);18291830transform_detail_string(detail, context);1831fp_gtk_render_focus (context, cr, x, y, width, height);18321833fp_gtk_style_context_restore (context);18341835}18361837static void gtk3_paint_handle(WidgetType widget_type, GtkStateType state_type,1838GtkShadowType shadow_type, const gchar *detail,1839gint x, gint y, gint width, gint height, GtkOrientation orientation)1840{1841gtk3_widget = gtk3_get_widget(widget_type);18421843GtkStyleContext* context = get_style(widget_type, detail);18441845GtkStateFlags flags = get_gtk_flags(state_type);1846fp_gtk_style_context_set_state(context, GTK_STATE_FLAG_PRELIGHT);18471848if (detail != 0 && !(strcmp(detail, "paned") == 0)) {1849transform_detail_string(detail, context);1850fp_gtk_style_context_add_class (context, "handlebox_bin");1851}18521853if (!(strcmp(detail, "paned") == 0)) {1854fp_gtk_render_handle(context, cr, x, y, width, height);1855fp_gtk_render_background(context, cr, x, y, width, height);1856} else {1857if (orientation == GTK_ORIENTATION_VERTICAL) {1858fp_gtk_render_handle(context, cr, x+width/2, y, 2, height);1859fp_gtk_render_background(context, cr, x+width/2, y, 2, height);1860} else {1861fp_gtk_render_handle(context, cr, x, y+height/2, width, 2);1862fp_gtk_render_background(context, cr, x, y+height/2, width, 2);1863}1864}18651866disposeOrRestoreContext(context);1867}18681869static void gtk3_paint_hline(WidgetType widget_type, GtkStateType state_type,1870const gchar *detail, gint x, gint y, gint width, gint height)1871{1872gtk3_widget = gtk3_get_widget(widget_type);18731874GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);18751876fp_gtk_style_context_save (context);18771878if (detail != 0) {1879transform_detail_string(detail, context);1880}18811882fp_gtk_render_line(context, cr, x, y, x + width, y);18831884fp_gtk_style_context_restore (context);1885}18861887static void gtk3_paint_vline(WidgetType widget_type, GtkStateType state_type,1888const gchar *detail, gint x, gint y, gint width, gint height)1889{1890gtk3_widget = gtk3_get_widget(widget_type);189118921893GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);18941895fp_gtk_style_context_save (context);18961897if (detail != 0) {1898transform_detail_string(detail, context);1899}19001901fp_gtk_render_line(context, cr, x, y, x, y + height);19021903fp_gtk_style_context_restore (context);1904}19051906static void gtk3_paint_option(WidgetType widget_type, gint synth_state,1907const gchar *detail, gint x, gint y, gint width, gint height)1908{1909GtkStyleContext* context = get_style(widget_type, detail);19101911GtkStateFlags flags = get_gtk_state_flags(synth_state);1912if (gtk3_version_3_14 && (synth_state & SELECTED)) {1913flags &= ~GTK_STATE_FLAG_SELECTED;1914flags |= GTK_STATE_FLAG_CHECKED;1915}1916fp_gtk_style_context_set_state(context, flags);19171918fp_gtk_render_background(context, cr, x, y, width, height);1919fp_gtk_render_frame(context, cr, x, y, width, height);1920fp_gtk_render_option(context, cr, x, y, width, height);1921disposeOrRestoreContext(context);1922}19231924static void gtk3_paint_shadow(WidgetType widget_type, GtkStateType state_type,1925GtkShadowType shadow_type, const gchar *detail,1926gint x, gint y, gint width, gint height,1927gint synth_state, GtkTextDirection dir)1928{1929if (shadow_type == GTK_SHADOW_NONE) {1930return;1931}1932gtk3_widget = gtk3_get_widget(widget_type);19331934/*1935* Some engines (e.g. clearlooks) will paint the shadow of certain1936* widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the1937* the text direction.1938*/1939gtk3_set_direction(gtk3_widget, dir);194019411942GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);1943fp_gtk_style_context_save (context);19441945if (detail) {1946transform_detail_string(detail, context);1947}19481949GtkStateFlags flags = get_gtk_flags(state_type);19501951if (synth_state & MOUSE_OVER) {1952flags |= GTK_STATE_FLAG_PRELIGHT;1953}19541955if (synth_state & FOCUSED) {1956flags |= GTK_STATE_FLAG_FOCUSED;1957}19581959fp_gtk_style_context_set_state (context, flags);19601961if (widget_type == COMBO_BOX_TEXT_FIELD) {1962width += height / 2;1963}1964fp_gtk_render_frame(context, cr, x, y, width, height);19651966fp_gtk_style_context_restore (context);19671968/*1969* Reset the text direction to the default value so that we don't1970* accidentally affect other operations and widgets.1971*/1972gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR);1973}19741975static void gtk3_paint_slider(WidgetType widget_type, GtkStateType state_type,1976GtkShadowType shadow_type, const gchar *detail,1977gint x, gint y, gint width, gint height, GtkOrientation orientation,1978gboolean has_focus)1979{1980GtkStyleContext *context = get_style(widget_type, detail);19811982GtkStateFlags flags = get_gtk_flags(state_type);19831984if (state_type == GTK_STATE_ACTIVE) {1985flags |= GTK_STATE_FLAG_PRELIGHT;1986}19871988if (has_focus) {1989flags |= GTK_STATE_FLAG_FOCUSED;1990}19911992fp_gtk_style_context_set_state (context, flags);19931994fp_gtk_render_background (context, cr, x, y, width, height);1995fp_gtk_render_frame(context, cr, x, y, width, height);1996(*fp_gtk_render_slider)(context, cr, x, y, width, height, orientation);1997disposeOrRestoreContext(context);1998}19992000static void gtk3_paint_background(WidgetType widget_type,2001GtkStateType state_type, gint x, gint y, gint width, gint height) {2002gtk3_widget = gtk3_get_widget(widget_type);20032004GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);2005fp_gtk_style_context_save (context);20062007GtkStateFlags flags = get_gtk_flags(state_type);20082009fp_gtk_style_context_set_state (context, flags);20102011fp_gtk_render_background (context, cr, x, y, width, height);20122013fp_gtk_style_context_restore (context);2014}20152016static GdkPixbuf *gtk3_get_stock_icon(gint widget_type, const gchar *stock_id,2017GtkIconSize size, GtkTextDirection direction, const char *detail)2018{2019int sz;20202021switch(size) {2022case GTK_ICON_SIZE_MENU:2023sz = 16;2024break;2025case GTK_ICON_SIZE_SMALL_TOOLBAR:2026sz = 18;2027break;2028case GTK_ICON_SIZE_LARGE_TOOLBAR:2029sz = 24;2030break;2031case GTK_ICON_SIZE_BUTTON:2032sz = 20;2033break;2034case GTK_ICON_SIZE_DND:2035sz = 32;2036break;2037case GTK_ICON_SIZE_DIALOG:2038sz = 48;2039break;2040default:2041sz = 0;2042break;2043}20442045init_containers();2046gtk3_widget = gtk3_get_widget((widget_type < 0) ? IMAGE : widget_type);2047(*fp_gtk_widget_set_direction)(gtk3_widget, direction);2048GtkIconTheme *icon_theme = fp_gtk_icon_theme_get_default();2049GdkPixbuf *result = fp_gtk_icon_theme_load_icon(icon_theme, stock_id, sz,2050GTK_ICON_LOOKUP_USE_BUILTIN, NULL);2051return result;2052}20532054static jboolean gtk3_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 gtk3_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 gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);2087}20882089static jboolean gtk3_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 = gtk3_get_stock_icon(widget_type, stock_id, size,2094direction, detail);2095return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);2096}20972098/*************************************************/2099static gint gtk3_get_xthickness(JNIEnv *env, WidgetType widget_type)2100{2101init_containers();21022103gtk3_widget = gtk3_get_widget(widget_type);2104GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);2105if (context) {2106GtkBorder padding;2107fp_gtk_style_context_get_padding(context, 0, &padding);2108return padding.left + 1;2109}2110return 0;2111}21122113static gint gtk3_get_ythickness(JNIEnv *env, WidgetType widget_type)2114{2115init_containers();21162117gtk3_widget = gtk3_get_widget(widget_type);2118GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);2119if (context) {2120GtkBorder padding;2121fp_gtk_style_context_get_padding(context, 0, &padding);2122return padding.top + 1;2123}2124return 0;2125}21262127/*************************************************/2128static guint8 recode_color(gdouble channel)2129{2130guint16 result = (guint16)(channel * 65535);2131if (result > 65535) {2132result = 65535;2133}2134return (guint8)( result >> 8);2135}21362137static GtkStateFlags gtk3_get_state_flags(GtkStateType state_type) {2138switch (state_type)2139{2140case GTK_STATE_NORMAL:2141return GTK_STATE_FLAG_NORMAL;2142case GTK_STATE_ACTIVE:2143return GTK_STATE_FLAG_ACTIVE;2144case GTK_STATE_PRELIGHT:2145return GTK_STATE_FLAG_PRELIGHT;2146case GTK_STATE_SELECTED:2147return GTK_STATE_FLAG_SELECTED;2148case GTK_STATE_INSENSITIVE:2149return GTK_STATE_FLAG_INSENSITIVE;2150case GTK_STATE_INCONSISTENT:2151return GTK_STATE_FLAG_INCONSISTENT;2152case GTK_STATE_FOCUSED:2153return GTK_STATE_FLAG_FOCUSED;2154}2155return 0;2156}215721582159static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b) {2160gdouble min;2161gdouble max;2162gdouble red;2163gdouble green;2164gdouble blue;2165gdouble h, l, s;2166gdouble delta;21672168red = *r;2169green = *g;2170blue = *b;21712172if (red > green)2173{2174if (red > blue)2175max = red;2176else2177max = blue;21782179if (green < blue)2180min = green;2181else2182min = blue;2183}2184else2185{2186if (green > blue)2187max = green;2188else2189max = blue;21902191if (red < blue)2192min = red;2193else2194min = blue;2195}21962197l = (max + min) / 2;2198s = 0;2199h = 0;22002201if (max != min)2202{2203if (l <= 0.5)2204s = (max - min) / (max + min);2205else2206s = (max - min) / (2 - max - min);22072208delta = max -min;2209if (red == max)2210h = (green - blue) / delta;2211else if (green == max)2212h = 2 + (blue - red) / delta;2213else if (blue == max)2214h = 4 + (red - green) / delta;22152216h *= 60;2217if (h < 0.0)2218h += 360;2219}22202221*r = h;2222*g = l;2223*b = s;2224}22252226static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s)2227{2228gdouble hue;2229gdouble lightness;2230gdouble saturation;2231gdouble m1, m2;2232gdouble r, g, b;22332234lightness = *l;2235saturation = *s;22362237if (lightness <= 0.5)2238m2 = lightness * (1 + saturation);2239else2240m2 = lightness + saturation - lightness * saturation;2241m1 = 2 * lightness - m2;22422243if (saturation == 0)2244{2245*h = lightness;2246*l = lightness;2247*s = lightness;2248}2249else2250{2251hue = *h + 120;2252while (hue > 360)2253hue -= 360;2254while (hue < 0)2255hue += 360;22562257if (hue < 60)2258r = m1 + (m2 - m1) * hue / 60;2259else if (hue < 180)2260r = m2;2261else if (hue < 240)2262r = m1 + (m2 - m1) * (240 - hue) / 60;2263else2264r = m1;22652266hue = *h;2267while (hue > 360)2268hue -= 360;2269while (hue < 0)2270hue += 360;22712272if (hue < 60)2273g = m1 + (m2 - m1) * hue / 60;2274else if (hue < 180)2275g = m2;2276else if (hue < 240)2277g = m1 + (m2 - m1) * (240 - hue) / 60;2278else2279g = m1;22802281hue = *h - 120;2282while (hue > 360)2283hue -= 360;2284while (hue < 0)2285hue += 360;22862287if (hue < 60)2288b = m1 + (m2 - m1) * hue / 60;2289else if (hue < 180)2290b = m2;2291else if (hue < 240)2292b = m1 + (m2 - m1) * (240 - hue) / 60;2293else2294b = m1;22952296*h = r;2297*l = g;2298*s = b;2299}2300}2301230223032304static void gtk3_style_shade (const GdkRGBA *a, GdkRGBA *b, gdouble k) {2305gdouble red = a->red;2306gdouble green = a->green;2307gdouble blue = a->blue;23082309rgb_to_hls (&red, &green, &blue);23102311green *= k;2312if (green > 1.0)2313green = 1.0;2314else if (green < 0.0)2315green = 0.0;23162317blue *= k;2318if (blue > 1.0)2319blue = 1.0;2320else if (blue < 0.0)2321blue = 0.0;23222323hls_to_rgb (&red, &green, &blue);23242325b->red = red;2326b->green = green;2327b->blue = blue;2328}23292330static GdkRGBA gtk3_get_color_for_flags(GtkStyleContext* context,2331GtkStateFlags flags, ColorType color_type) {2332GdkRGBA c, color;2333color.alpha = 1;23342335switch (color_type)2336{2337case FOREGROUND:2338case TEXT_FOREGROUND:2339fp_gtk_style_context_get_color(context, flags, &color);2340break;2341case BACKGROUND:2342case TEXT_BACKGROUND:2343fp_gtk_style_context_get_background_color(context, flags, &color);2344break;2345case LIGHT:2346c = gtk3_get_color_for_flags(context, flags, BACKGROUND);2347gtk3_style_shade(&c, &color, LIGHTNESS_MULT);2348break;2349case DARK:2350c = gtk3_get_color_for_flags(context, flags, BACKGROUND);2351gtk3_style_shade (&c, &color, DARKNESS_MULT);2352break;2353case MID:2354{2355GdkRGBA c1 = gtk3_get_color_for_flags(context, flags, LIGHT);2356GdkRGBA c2 = gtk3_get_color_for_flags(context, flags, DARK);2357color.red = (c1.red + c2.red) / 2;2358color.green = (c1.green + c2.green) / 2;2359color.blue = (c1.blue + c2.blue) / 2;2360}2361break;2362case FOCUS:2363case BLACK:2364color.red = 0;2365color.green = 0;2366color.blue = 0;2367break;2368case WHITE:2369color.red = 1;2370color.green = 1;2371color.blue = 1;2372break;2373}2374return color;2375}23762377static gint gtk3_get_color_for_state(JNIEnv *env, WidgetType widget_type,2378GtkStateType state_type, ColorType color_type)2379{23802381gint result = 0;23822383GtkStateFlags flags = gtk3_get_state_flags(state_type);23842385init_containers();23862387if (gtk3_version_3_20) {2388if ((widget_type == TEXT_FIELD || widget_type == PASSWORD_FIELD || widget_type == SPINNER_TEXT_FIELD ||2389widget_type == FORMATTED_TEXT_FIELD) && state_type == GTK_STATE_SELECTED && color_type == TEXT_BACKGROUND) {2390widget_type = TEXT_AREA;2391}2392}23932394GtkStyleContext* context = NULL;2395if (widget_type == TOOL_TIP) {2396context = get_style(widget_type, "tooltip");2397} else {2398gtk3_widget = gtk3_get_widget(widget_type);2399context = fp_gtk_widget_get_style_context(gtk3_widget);2400}2401if (widget_type == CHECK_BOX_MENU_ITEM2402|| widget_type == RADIO_BUTTON_MENU_ITEM) {2403flags &= GTK_STATE_FLAG_NORMAL | GTK_STATE_FLAG_SELECTED2404| GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_FOCUSED;2405}24062407GdkRGBA color = gtk3_get_color_for_flags(context, flags, color_type);24082409if (recode_color(color.alpha) == 0) {2410color = gtk3_get_color_for_flags(2411fp_gtk_widget_get_style_context(gtk3_get_widget(INTERNAL_FRAME)),24120, BACKGROUND);2413}24142415result = recode_color(color.alpha) << 24 | recode_color(color.red) << 16 |2416recode_color(color.green) << 8 | recode_color(color.blue);2417if (widget_type == TOOL_TIP) {2418disposeOrRestoreContext(context);2419}2420return result;2421}24222423/*************************************************/2424static jobject create_Boolean(JNIEnv *env, jboolean boolean_value);2425static jobject create_Integer(JNIEnv *env, jint int_value);2426static jobject create_Long(JNIEnv *env, jlong long_value);2427static jobject create_Float(JNIEnv *env, jfloat float_value);2428static jobject create_Double(JNIEnv *env, jdouble double_value);2429static jobject create_Character(JNIEnv *env, jchar char_value);2430static jobject create_Insets(JNIEnv *env, GtkBorder *border);24312432static jobject gtk3_get_class_value(JNIEnv *env, WidgetType widget_type,2433const char* key)2434{2435init_containers();24362437gtk3_widget = gtk3_get_widget(widget_type);24382439GValue value = { 0, { { 0 } } };24402441GParamSpec* param = (*fp_gtk_widget_class_find_style_property)(2442((GTypeInstance*)gtk3_widget)->g_class, key);2443if ( param )2444{2445(*fp_g_value_init)( &value, param->value_type );2446(*fp_gtk_widget_style_get_property)(gtk3_widget, key, &value);24472448if ((*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN ))2449{2450gboolean val = (*fp_g_value_get_boolean)(&value);2451return create_Boolean(env, (jboolean)val);2452}2453else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR ))2454{2455gchar val = (*fp_g_value_get_char)(&value);2456return create_Character(env, (jchar)val);2457}2458else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR ))2459{2460guchar val = (*fp_g_value_get_uchar)(&value);2461return create_Character(env, (jchar)val);2462}2463else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT ))2464{2465gint val = (*fp_g_value_get_int)(&value);2466return create_Integer(env, (jint)val);2467}2468else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT ))2469{2470guint val = (*fp_g_value_get_uint)(&value);2471return create_Integer(env, (jint)val);2472}2473else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_LONG ))2474{2475glong val = (*fp_g_value_get_long)(&value);2476return create_Long(env, (jlong)val);2477}2478else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG ))2479{2480gulong val = (*fp_g_value_get_ulong)(&value);2481return create_Long(env, (jlong)val);2482}2483else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 ))2484{2485gint64 val = (*fp_g_value_get_int64)(&value);2486return create_Long(env, (jlong)val);2487}2488else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 ))2489{2490guint64 val = (*fp_g_value_get_uint64)(&value);2491return create_Long(env, (jlong)val);2492}2493else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT ))2494{2495gfloat val = (*fp_g_value_get_float)(&value);2496return create_Float(env, (jfloat)val);2497}2498else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE ))2499{2500gdouble val = (*fp_g_value_get_double)(&value);2501return create_Double(env, (jdouble)val);2502}2503else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM ))2504{2505gint val = (*fp_g_value_get_enum)(&value);2506return create_Integer(env, (jint)val);2507}2508else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS ))2509{2510guint val = (*fp_g_value_get_flags)(&value);2511return create_Integer(env, (jint)val);2512}2513else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_STRING ))2514{2515const gchar* val = (*fp_g_value_get_string)(&value);25162517/* We suppose that all values come in C locale and2518* utf-8 representation of a string is the same as2519* the string itself. If this isn't so we should2520* use g_convert.2521*/2522return (*env)->NewStringUTF(env, val);2523}2524else if ((*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER ))2525{2526GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value);2527return border ? create_Insets(env, border) : NULL;2528}25292530/* TODO: Other types are not supported yet.*/2531/* else if((*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM ))2532{2533GParamSpec* val = (*fp_g_value_get_param)(&value);2534printf( "Param: %p\n", val );2535}2536else if((*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED ))2537{2538gpointer* val = (*fp_g_value_get_boxed)(&value);2539printf( "Boxed: %p\n", val );2540}2541else if((*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER ))2542{2543gpointer* val = (*fp_g_value_get_pointer)(&value);2544printf( "Pointer: %p\n", val );2545}2546else if((*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT ))2547{2548GObject* val = (GObject*)(*fp_g_value_get_object)(&value);2549printf( "Object: %p\n", val );2550}*/2551}25522553return NULL;2554}25552556static void gtk3_set_range_value(WidgetType widget_type, jdouble value,2557jdouble min, jdouble max, jdouble visible)2558{2559GtkAdjustment *adj;25602561gtk3_widget = gtk3_get_widget(widget_type);25622563adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk3_widget);25642565fp_gtk_adjustment_set_value(adj, value);2566fp_gtk_adjustment_set_lower(adj, min);2567fp_gtk_adjustment_set_upper(adj, max);2568fp_gtk_adjustment_set_page_size(adj, visible);2569}25702571/*************************************************/2572static jobject create_Object(JNIEnv *env, jmethodID *cid,2573const char* class_name,2574const char* signature,2575jvalue* value)2576{2577jclass class;2578jobject result;25792580class = (*env)->FindClass(env, class_name);2581if (class == NULL)2582return NULL; /* can't find/load the class, exception thrown */25832584if (*cid == NULL)2585{2586*cid = (*env)->GetMethodID(env, class, "<init>", signature);2587if (*cid == NULL)2588{2589(*env)->DeleteLocalRef(env, class);2590return NULL; /* can't find/get the method, exception thrown */2591}2592}25932594result = (*env)->NewObjectA(env, class, *cid, value);25952596(*env)->DeleteLocalRef(env, class);2597return result;2598}25992600jobject create_Boolean(JNIEnv *env, jboolean boolean_value)2601{2602static jmethodID cid = NULL;2603jvalue value;26042605value.z = boolean_value;26062607return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value);2608}26092610jobject create_Integer(JNIEnv *env, jint int_value)2611{2612static jmethodID cid = NULL;2613jvalue value;26142615value.i = int_value;26162617return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value);2618}26192620jobject create_Long(JNIEnv *env, jlong long_value)2621{2622static jmethodID cid = NULL;2623jvalue value;26242625value.j = long_value;26262627return create_Object(env, &cid, "java/lang/Long", "(J)V", &value);2628}26292630jobject create_Float(JNIEnv *env, jfloat float_value)2631{2632static jmethodID cid = NULL;2633jvalue value;26342635value.f = float_value;26362637return create_Object(env, &cid, "java/lang/Float", "(F)V", &value);2638}26392640jobject create_Double(JNIEnv *env, jdouble double_value)2641{2642static jmethodID cid = NULL;2643jvalue value;26442645value.d = double_value;26462647return create_Object(env, &cid, "java/lang/Double", "(D)V", &value);2648}26492650jobject create_Character(JNIEnv *env, jchar char_value)2651{2652static jmethodID cid = NULL;2653jvalue value;26542655value.c = char_value;26562657return create_Object(env, &cid, "java/lang/Character", "(C)V", &value);2658}265926602661jobject create_Insets(JNIEnv *env, GtkBorder *border)2662{2663static jmethodID cid = NULL;2664jvalue values[4];26652666values[0].i = border->top;2667values[1].i = border->left;2668values[2].i = border->bottom;2669values[3].i = border->right;26702671return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values);2672}26732674/*********************************************/2675static jstring gtk3_get_pango_font_name(JNIEnv *env, WidgetType widget_type)2676{2677init_containers();26782679gtk3_widget = gtk3_get_widget(widget_type);2680jstring result = NULL;2681GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);2682if (context)2683{2684PangoFontDescription* fd = fp_gtk_style_context_get_font(context, 0);2685gchar* val = (*fp_pango_font_description_to_string)(fd);2686result = (*env)->NewStringUTF(env, val);2687(*fp_g_free)( val );2688}26892690return result;2691}26922693/***********************************************/2694static jobject get_string_property(JNIEnv *env, GtkSettings* settings,2695const gchar* key) {2696jobject result = NULL;2697gchar* strval = NULL;26982699(*fp_g_object_get)(settings, key, &strval, NULL);2700result = (*env)->NewStringUTF(env, strval);2701(*fp_g_free)(strval);27022703return result;2704}27052706static jobject get_integer_property(JNIEnv *env, GtkSettings* settings,2707const gchar* key) {2708gint intval = 0;2709(*fp_g_object_get)(settings, key, &intval, NULL);2710return create_Integer(env, intval);2711}27122713static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings,2714const gchar* key) {2715gint intval = 0;2716(*fp_g_object_get)(settings, key, &intval, NULL);2717return create_Boolean(env, intval);2718}27192720static jobject gtk3_get_setting(JNIEnv *env, Setting property)2721{2722GtkSettings* settings = (*fp_gtk_settings_get_default)();27232724switch (property)2725{2726case GTK_FONT_NAME:2727return get_string_property(env, settings, "gtk-font-name");2728case GTK_ICON_SIZES:2729return get_string_property(env, settings, "gtk-icon-sizes");2730case GTK_CURSOR_BLINK:2731return get_boolean_property(env, settings, "gtk-cursor-blink");2732case GTK_CURSOR_BLINK_TIME:2733return get_integer_property(env, settings, "gtk-cursor-blink-time");2734}27352736return NULL;2737}27382739static void transform_detail_string (const gchar *detail,2740GtkStyleContext *context) {2741if (!detail)2742return;27432744if (strcmp (detail, "arrow") == 0)2745fp_gtk_style_context_add_class (context, "arrow");2746else if (strcmp (detail, "button") == 0)2747fp_gtk_style_context_add_class (context, "button");2748else if (strcmp (detail, "buttondefault") == 0)2749{2750fp_gtk_style_context_add_class (context, "button");2751fp_gtk_style_context_add_class (context, "default");2752}2753else if (strcmp (detail, "calendar") == 0)2754fp_gtk_style_context_add_class (context, "calendar");2755else if (strcmp (detail, "cellcheck") == 0)2756{2757fp_gtk_style_context_add_class (context, "cell");2758fp_gtk_style_context_add_class (context, "check");2759}2760else if (strcmp (detail, "cellradio") == 0)2761{2762fp_gtk_style_context_add_class (context, "cell");2763fp_gtk_style_context_add_class (context, "radio");2764}2765else if (strcmp (detail, "checkbutton") == 0)2766fp_gtk_style_context_add_class (context, "check");2767else if (strcmp (detail, "check") == 0)2768{2769fp_gtk_style_context_add_class (context, "check");2770fp_gtk_style_context_add_class (context, "menu");2771}2772else if (strcmp (detail, "radiobutton") == 0)2773{2774fp_gtk_style_context_add_class (context, "radio");2775}2776else if (strcmp (detail, "option") == 0)2777{2778fp_gtk_style_context_add_class (context, "radio");2779fp_gtk_style_context_add_class (context, "menu");2780}2781else if (strcmp (detail, "entry") == 0 ||2782strcmp (detail, "entry_bg") == 0)2783fp_gtk_style_context_add_class (context, "entry");2784else if (strcmp (detail, "expander") == 0)2785fp_gtk_style_context_add_class (context, "expander");2786else if (strcmp (detail, "tooltip") == 0)2787fp_gtk_style_context_add_class (context, "tooltip");2788else if (strcmp (detail, "frame") == 0)2789fp_gtk_style_context_add_class (context, "frame");2790else if (strcmp (detail, "scrolled_window") == 0)2791fp_gtk_style_context_add_class (context, "scrolled-window");2792else if (strcmp (detail, "viewport") == 0 ||2793strcmp (detail, "viewportbin") == 0)2794fp_gtk_style_context_add_class (context, "viewport");2795else if (strncmp (detail, "trough", 6) == 0)2796fp_gtk_style_context_add_class (context, "trough");2797else if (strcmp (detail, "spinbutton") == 0)2798fp_gtk_style_context_add_class (context, "spinbutton");2799else if (strcmp (detail, "spinbutton_up") == 0)2800{2801fp_gtk_style_context_add_class (context, "spinbutton");2802fp_gtk_style_context_add_class (context, "button");2803fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);2804}2805else if (strcmp (detail, "spinbutton_down") == 0)2806{2807fp_gtk_style_context_add_class (context, "spinbutton");2808fp_gtk_style_context_add_class (context, "button");2809fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);2810}2811else if ((detail[0] == 'h' || detail[0] == 'v') &&2812strncmp (&detail[1], "scrollbar_", 9) == 0)2813{2814fp_gtk_style_context_add_class (context, "button");2815fp_gtk_style_context_add_class (context, "scrollbar");2816}2817else if (strcmp (detail, "slider") == 0)2818{2819fp_gtk_style_context_add_class (context, "slider");2820fp_gtk_style_context_add_class (context, "scrollbar");2821}2822else if (strcmp (detail, "vscale") == 0 ||2823strcmp (detail, "hscale") == 0)2824{2825fp_gtk_style_context_add_class (context, "slider");2826fp_gtk_style_context_add_class (context, "scale");2827}2828else if (strcmp (detail, "menuitem") == 0)2829{2830fp_gtk_style_context_add_class (context, "menuitem");2831fp_gtk_style_context_add_class (context, "menu");2832}2833else if (strcmp (detail, "menu") == 0)2834{2835fp_gtk_style_context_add_class (context, "popup");2836fp_gtk_style_context_add_class (context, "menu");2837}2838else if (strcmp (detail, "accellabel") == 0)2839fp_gtk_style_context_add_class (context, "accelerator");2840else if (strcmp (detail, "menubar") == 0)2841fp_gtk_style_context_add_class (context, "menubar");2842else if (strcmp (detail, "base") == 0)2843fp_gtk_style_context_add_class (context, "background");2844else if (strcmp (detail, "bar") == 0 ||2845strcmp (detail, "progressbar") == 0)2846fp_gtk_style_context_add_class (context, "progressbar");2847else if (strcmp (detail, "toolbar") == 0)2848fp_gtk_style_context_add_class (context, "toolbar");2849else if (strcmp (detail, "handlebox_bin") == 0)2850fp_gtk_style_context_add_class (context, "dock");2851else if (strcmp (detail, "notebook") == 0)2852fp_gtk_style_context_add_class (context, "notebook");2853else if (strcmp (detail, "tab") == 0)2854{2855fp_gtk_style_context_add_class (context, "notebook");2856fp_gtk_style_context_add_region (context, "tab", 0);2857} else if (strcmp (detail, "paned") == 0) {2858fp_gtk_style_context_add_class (context, "pane-separator");2859}2860else if (fp_g_str_has_prefix (detail, "cell"))2861{2862GtkRegionFlags row, col;2863gboolean ruled = FALSE;2864gchar** tokens;2865guint i;28662867tokens = fp_g_strsplit (detail, "_", -1);2868row = col = 0;2869i = 0;28702871while (tokens[i])2872{2873if (strcmp (tokens[i], "even") == 0)2874row |= GTK_REGION_EVEN;2875else if (strcmp (tokens[i], "odd") == 0)2876row |= GTK_REGION_ODD;2877else if (strcmp (tokens[i], "start") == 0)2878col |= GTK_REGION_FIRST;2879else if (strcmp (tokens[i], "end") == 0)2880col |= GTK_REGION_LAST;2881else if (strcmp (tokens[i], "ruled") == 0)2882ruled = TRUE;2883else if (strcmp (tokens[i], "sorted") == 0)2884col |= GTK_REGION_SORTED;28852886i++;2887}28882889if (!ruled)2890row &= ~(GTK_REGION_EVEN | GTK_REGION_ODD);28912892fp_gtk_style_context_add_class (context, "cell");2893fp_gtk_style_context_add_region (context, "row", row);2894fp_gtk_style_context_add_region (context, "column", col);28952896fp_g_strfreev (tokens);2897}2898}28992900static GdkWindow* gtk3_get_window(void *widget) {2901return fp_gtk_widget_get_window((GtkWidget*)widget);2902}29032904static void gtk3_init(GtkApi* gtk) {2905gtk->version = GTK_3;29062907gtk->show_uri_load = >k3_show_uri_load;2908gtk->unload = >k3_unload;2909gtk->flush_event_loop = &flush_gtk_event_loop;2910gtk->gtk_check_version = fp_gtk_check_version;2911gtk->get_setting = >k3_get_setting;29122913gtk->paint_arrow = >k3_paint_arrow;2914gtk->paint_box = >k3_paint_box;2915gtk->paint_box_gap = >k3_paint_box_gap;2916gtk->paint_expander = >k3_paint_expander;2917gtk->paint_extension = >k3_paint_extension;2918gtk->paint_flat_box = >k3_paint_flat_box;2919gtk->paint_focus = >k3_paint_focus;2920gtk->paint_handle = >k3_paint_handle;2921gtk->paint_hline = >k3_paint_hline;2922gtk->paint_vline = >k3_paint_vline;2923gtk->paint_option = >k3_paint_option;2924gtk->paint_shadow = >k3_paint_shadow;2925gtk->paint_slider = >k3_paint_slider;2926gtk->paint_background = >k3_paint_background;2927gtk->paint_check = >k3_paint_check;2928gtk->set_range_value = >k3_set_range_value;29292930gtk->init_painting = >k3_init_painting;2931gtk->copy_image = >k3_copy_image;29322933gtk->get_xthickness = >k3_get_xthickness;2934gtk->get_ythickness = >k3_get_ythickness;2935gtk->get_color_for_state = >k3_get_color_for_state;2936gtk->get_class_value = >k3_get_class_value;29372938gtk->get_pango_font_name = >k3_get_pango_font_name;2939gtk->get_icon_data = >k3_get_icon_data;2940gtk->get_file_icon_data = >k3_get_file_icon_data;2941gtk->gdk_threads_enter = fp_gdk_threads_enter;2942gtk->gdk_threads_leave = fp_gdk_threads_leave;2943gtk->gtk_show_uri = fp_gtk_show_uri;2944gtk->g_free = fp_g_free;29452946gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename;2947gtk->gtk_widget_hide = fp_gtk_widget_hide;2948gtk->gtk_main_quit = fp_gtk_main_quit;2949gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new;2950gtk->gtk_file_chooser_set_current_folder =2951fp_gtk_file_chooser_set_current_folder;2952gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename;2953gtk->gtk_file_chooser_set_current_name =2954fp_gtk_file_chooser_set_current_name;2955gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom;2956gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter;2957gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type;2958gtk->gtk_file_filter_new = fp_gtk_file_filter_new;2959gtk->gtk_file_chooser_set_do_overwrite_confirmation =2960fp_gtk_file_chooser_set_do_overwrite_confirmation;2961gtk->gtk_file_chooser_set_select_multiple =2962fp_gtk_file_chooser_set_select_multiple;2963gtk->gtk_file_chooser_get_current_folder =2964fp_gtk_file_chooser_get_current_folder;2965gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames;2966gtk->gtk_g_slist_length = fp_gtk_g_slist_length;2967gtk->g_signal_connect_data = fp_g_signal_connect_data;2968gtk->gtk_widget_show = fp_gtk_widget_show;2969gtk->gtk_main = fp_gtk_main;2970gtk->gtk_main_level = fp_gtk_main_level;2971gtk->g_path_get_dirname = fp_g_path_get_dirname;2972gtk->gtk_widget_destroy = fp_gtk_widget_destroy;2973gtk->gtk_window_present = fp_gtk_window_present;2974gtk->gtk_window_move = fp_gtk_window_move;2975gtk->gtk_window_resize = fp_gtk_window_resize;2976gtk->get_window = >k3_get_window;29772978gtk->g_object_unref = fp_g_object_unref;2979gtk->g_list_append = fp_g_list_append;2980gtk->g_list_free = fp_g_list_free;2981gtk->g_list_free_full = fp_g_list_free_full;2982}298329842985