1 /* 2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 #include <dlfcn.h> 26 #include <setjmp.h> 27 #include <X11/Xlib.h> 28 #include <limits.h> 29 #include <string.h> 30 #include "gtk3_interface.h" 31 #include "java_awt_Transparency.h" 32 #include "sizecalc.h" 33 #include <jni_util.h> 34 #include <stdio.h> 35 #include "awt.h" 36 37 static void *gtk3_libhandle = NULL; 38 static void *gthread_libhandle = NULL; 39 40 static jmp_buf j; 41 42 /* Widgets */ 43 static GtkWidget *gtk3_widget = NULL; 44 static GtkWidget *gtk3_window = NULL; 45 static GtkFixed *gtk3_fixed = NULL; 46 static GtkStyleProvider *gtk3_css = NULL; 47 48 /* Paint system */ 49 static cairo_surface_t *surface = NULL; 50 static cairo_t *cr = NULL; 51 52 static const char ENV_PREFIX[] = "GTK_MODULES="; 53 54 static GtkWidget *gtk3_widgets[_GTK_WIDGET_TYPE_SIZE]; 55 56 static void throw_exception(JNIEnv *env, const char* name, const char* message) 57 { 58 jclass class = (*env)->FindClass(env, name); 59 60 if (class != NULL) 61 (*env)->ThrowNew(env, class, message); 62 63 (*env)->DeleteLocalRef(env, class); 64 } 65 66 static void gtk3_add_state(GtkWidget *widget, GtkStateType state) { 67 GtkStateType old_state = fp_gtk_widget_get_state(widget); 68 fp_gtk_widget_set_state(widget, old_state | state); 69 } 70 71 static void gtk3_remove_state(GtkWidget *widget, GtkStateType state) { 72 GtkStateType old_state = fp_gtk_widget_get_state(widget); 73 fp_gtk_widget_set_state(widget, old_state & ~state); 74 } 75 76 /* This is a workaround for the bug: 77 * http://sourceware.org/bugzilla/show_bug.cgi?id=1814 78 * (dlsym/dlopen clears dlerror state) 79 * This bug is specific to Linux, but there is no harm in 80 * applying this workaround on Solaris as well. 81 */ 82 static void* dl_symbol(const char* name) 83 { 84 void* result = dlsym(gtk3_libhandle, name); 85 if (!result) 86 longjmp(j, NO_SYMBOL_EXCEPTION); 87 88 return result; 89 } 90 91 static void* dl_symbol_gthread(const char* name) 92 { 93 void* result = dlsym(gthread_libhandle, name); 94 if (!result) 95 longjmp(j, NO_SYMBOL_EXCEPTION); 96 97 return result; 98 } 99 100 gboolean gtk3_check(const char* lib_name, gboolean load) 101 { 102 if (gtk3_libhandle != NULL) { 103 /* We've already successfully opened the GTK libs, so return true. */ 104 return TRUE; 105 } else { 106 #ifdef RTLD_NOLOAD 107 void *lib = dlopen(lib_name, RTLD_LAZY | RTLD_NOLOAD); 108 if (!load || lib != NULL) { 109 return lib != NULL; 110 } 111 #else 112 #ifdef _AIX 113 /* On AIX we could implement this with the help of loadquery(L_GETINFO, ..) */ 114 /* (see reload_table() in hotspot/src/os/aix/vm/loadlib_aix.cpp) but it is */ 115 /* probably not worth it because most AIX servers don't have GTK libs anyway */ 116 #endif 117 #endif 118 return dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL) != NULL; 119 } 120 } 121 122 #define ADD_SUPPORTED_ACTION(actionStr) \ 123 do { \ 124 jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, \ 125 "Ljava/awt/Desktop$Action;"); \ 126 if (!(*env)->ExceptionCheck(env)) { \ 127 jobject action = (*env)->GetStaticObjectField(env, cls_action, \ 128 fld_action); \ 129 (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, \ 130 action); \ 131 } else { \ 132 (*env)->ExceptionClear(env); \ 133 } \ 134 } while(0); 135 136 137 static void update_supported_actions(JNIEnv *env) { 138 GVfs * (*fp_g_vfs_get_default) (void); 139 const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs); 140 const gchar * const * schemes = NULL; 141 142 jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action"); 143 CHECK_NULL(cls_action); 144 jclass cls_xDesktopPeer = (*env)-> 145 FindClass(env, "sun/awt/X11/XDesktopPeer"); 146 CHECK_NULL(cls_xDesktopPeer); 147 jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, 148 cls_xDesktopPeer, "supportedActions", "Ljava/util/List;"); 149 CHECK_NULL(fld_supportedActions); 150 jobject supportedActions = (*env)->GetStaticObjectField(env, 151 cls_xDesktopPeer, fld_supportedActions); 152 153 jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList"); 154 CHECK_NULL(cls_arrayList); 155 jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", 156 "(Ljava/lang/Object;)Z"); 157 CHECK_NULL(mid_arrayListAdd); 158 jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, 159 "clear", "()V"); 160 CHECK_NULL(mid_arrayListClear); 161 162 (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear); 163 164 ADD_SUPPORTED_ACTION("OPEN"); 165 166 /** 167 * gtk_show_uri() documentation says: 168 * 169 * > you need to install gvfs to get support for uri schemes such as http:// 170 * > or ftp://, as only local files are handled by GIO itself. 171 * 172 * So OPEN action was safely added here. 173 * However, it looks like Solaris 11 have gvfs support only for 32-bit 174 * applications only by default. 175 */ 176 177 fp_g_vfs_get_default = dl_symbol("g_vfs_get_default"); 178 fp_g_vfs_get_supported_uri_schemes = 179 dl_symbol("g_vfs_get_supported_uri_schemes"); 180 dlerror(); 181 182 if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) { 183 GVfs * vfs = fp_g_vfs_get_default(); 184 schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL; 185 if (schemes) { 186 int i = 0; 187 while (schemes[i]) { 188 if (strcmp(schemes[i], "http") == 0) { 189 ADD_SUPPORTED_ACTION("BROWSE"); 190 ADD_SUPPORTED_ACTION("MAIL"); 191 break; 192 } 193 i++; 194 } 195 } 196 } else { 197 #ifdef DEBUG 198 fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n"); 199 #endif /* DEBUG */ 200 } 201 202 } 203 /** 204 * Functions for awt_Desktop.c 205 */ 206 static gboolean gtk3_show_uri_load(JNIEnv *env) { 207 gboolean success = FALSE; 208 dlerror(); 209 fp_gtk_show_uri = dl_symbol("gtk_show_uri"); 210 const char *dlsym_error = dlerror(); 211 if (dlsym_error) { 212 #ifdef DEBUG 213 fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error); 214 #endif /* DEBUG */ 215 } else if (fp_gtk_show_uri == NULL) { 216 #ifdef DEBUG 217 fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n"); 218 #endif /* DEBUG */ 219 } else { 220 gtk->gtk_show_uri = fp_gtk_show_uri; 221 update_supported_actions(env); 222 success = TRUE; 223 } 224 return success; 225 } 226 227 /** 228 * Functions for sun_awt_X11_GtkFileDialogPeer.c 229 */ 230 static void gtk3_file_chooser_load() 231 { 232 fp_gtk_file_chooser_get_filename = dl_symbol( 233 "gtk_file_chooser_get_filename"); 234 fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new"); 235 fp_gtk_file_chooser_set_current_folder = dl_symbol( 236 "gtk_file_chooser_set_current_folder"); 237 fp_gtk_file_chooser_set_filename = dl_symbol( 238 "gtk_file_chooser_set_filename"); 239 fp_gtk_file_chooser_set_current_name = dl_symbol( 240 "gtk_file_chooser_set_current_name"); 241 fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom"); 242 fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter"); 243 fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type"); 244 fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new"); 245 fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol( 246 "gtk_file_chooser_set_do_overwrite_confirmation"); 247 fp_gtk_file_chooser_set_select_multiple = dl_symbol( 248 "gtk_file_chooser_set_select_multiple"); 249 fp_gtk_file_chooser_get_current_folder = dl_symbol( 250 "gtk_file_chooser_get_current_folder"); 251 fp_gtk_file_chooser_get_filenames = dl_symbol( 252 "gtk_file_chooser_get_filenames"); 253 fp_gtk_g_slist_length = dl_symbol("g_slist_length"); 254 fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_window_get_xid"); 255 } 256 257 static void empty() {} 258 259 static gboolean gtk3_version_3_10 = TRUE; 260 static gboolean gtk3_version_3_14 = FALSE; 261 262 GtkApi* gtk3_load(JNIEnv *env, const char* lib_name) 263 { 264 gboolean result; 265 int i; 266 int (*handler)(); 267 int (*io_handler)(); 268 char *gtk_modules_env; 269 gtk3_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); 270 if (gtk3_libhandle == NULL) { 271 return FALSE; 272 } 273 274 gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); 275 if (gthread_libhandle == NULL) { 276 gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL); 277 if (gthread_libhandle == NULL) 278 return FALSE; 279 } 280 281 if (setjmp(j) == 0) 282 { 283 fp_gtk_check_version = dl_symbol("gtk_check_version"); 284 285 /* GLib */ 286 fp_glib_check_version = dlsym(gtk3_libhandle, "glib_check_version"); 287 if (!fp_glib_check_version) { 288 dlerror(); 289 } 290 fp_g_free = dl_symbol("g_free"); 291 fp_g_object_unref = dl_symbol("g_object_unref"); 292 293 fp_g_main_context_iteration = 294 dl_symbol("g_main_context_iteration"); 295 296 fp_g_value_init = dl_symbol("g_value_init"); 297 fp_g_type_is_a = dl_symbol("g_type_is_a"); 298 fp_g_value_get_boolean = dl_symbol("g_value_get_boolean"); 299 fp_g_value_get_char = dl_symbol("g_value_get_char"); 300 fp_g_value_get_uchar = dl_symbol("g_value_get_uchar"); 301 fp_g_value_get_int = dl_symbol("g_value_get_int"); 302 fp_g_value_get_uint = dl_symbol("g_value_get_uint"); 303 fp_g_value_get_long = dl_symbol("g_value_get_long"); 304 fp_g_value_get_ulong = dl_symbol("g_value_get_ulong"); 305 fp_g_value_get_int64 = dl_symbol("g_value_get_int64"); 306 fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64"); 307 fp_g_value_get_float = dl_symbol("g_value_get_float"); 308 fp_g_value_get_double = dl_symbol("g_value_get_double"); 309 fp_g_value_get_string = dl_symbol("g_value_get_string"); 310 fp_g_value_get_enum = dl_symbol("g_value_get_enum"); 311 fp_g_value_get_flags = dl_symbol("g_value_get_flags"); 312 fp_g_value_get_param = dl_symbol("g_value_get_param"); 313 fp_g_value_get_boxed = dl_symbol("g_value_get_boxed"); 314 fp_g_value_get_pointer = dl_symbol("g_value_get_pointer"); 315 316 fp_g_object_get = dl_symbol("g_object_get"); 317 fp_g_object_set = dl_symbol("g_object_set"); 318 319 fp_g_str_has_prefix = dl_symbol("g_str_has_prefix"); 320 fp_g_strsplit = dl_symbol("g_strsplit"); 321 fp_g_strfreev = dl_symbol("g_strfreev"); 322 323 /* GDK */ 324 fp_gdk_get_default_root_window = 325 dl_symbol("gdk_get_default_root_window"); 326 327 /* Pixbuf */ 328 fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new"); 329 fp_gdk_pixbuf_new_from_file = 330 dl_symbol("gdk_pixbuf_new_from_file"); 331 fp_gdk_pixbuf_get_from_drawable = 332 dl_symbol("gdk_pixbuf_get_from_window"); 333 fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width"); 334 fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height"); 335 fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels"); 336 fp_gdk_pixbuf_get_rowstride = 337 dl_symbol("gdk_pixbuf_get_rowstride"); 338 fp_gdk_pixbuf_get_has_alpha = 339 dl_symbol("gdk_pixbuf_get_has_alpha"); 340 fp_gdk_pixbuf_get_bits_per_sample = 341 dl_symbol("gdk_pixbuf_get_bits_per_sample"); 342 fp_gdk_pixbuf_get_n_channels = 343 dl_symbol("gdk_pixbuf_get_n_channels"); 344 fp_gdk_pixbuf_get_colorspace = 345 dl_symbol("gdk_pixbuf_get_colorspace"); 346 347 fp_cairo_image_surface_create = dl_symbol("cairo_image_surface_create"); 348 fp_cairo_surface_destroy = dl_symbol("cairo_surface_destroy"); 349 fp_cairo_create = dl_symbol("cairo_create"); 350 fp_cairo_destroy = dl_symbol("cairo_destroy"); 351 fp_cairo_fill = dl_symbol("cairo_fill"); 352 fp_cairo_rectangle = dl_symbol("cairo_rectangle"); 353 fp_cairo_set_source_rgb = dl_symbol("cairo_set_source_rgb"); 354 fp_cairo_set_source_rgba = dl_symbol("cairo_set_source_rgba"); 355 fp_cairo_surface_flush = dl_symbol("cairo_surface_flush"); 356 fp_cairo_paint = dl_symbol("cairo_paint"); 357 fp_cairo_clip = dl_symbol("cairo_clip"); 358 fp_cairo_image_surface_get_data = 359 dl_symbol("cairo_image_surface_get_data"); 360 fp_cairo_image_surface_get_stride = 361 dl_symbol("cairo_image_surface_get_stride"); 362 363 fp_gdk_pixbuf_get_from_surface = 364 dl_symbol("gdk_pixbuf_get_from_surface"); 365 366 fp_gtk_widget_get_state = dl_symbol("gtk_widget_get_state"); 367 fp_gtk_widget_set_state = dl_symbol("gtk_widget_set_state"); 368 369 fp_gtk_widget_is_focus = dl_symbol("gtk_widget_is_focus"); 370 fp_gtk_widget_set_allocation = dl_symbol("gtk_widget_set_allocation"); 371 fp_gtk_widget_get_parent = dl_symbol("gtk_widget_get_parent"); 372 fp_gtk_widget_get_window = dl_symbol("gtk_widget_get_window"); 373 374 fp_gtk_widget_get_style_context = 375 dl_symbol("gtk_widget_get_style_context"); 376 fp_gtk_style_context_get_color = 377 dl_symbol("gtk_style_context_get_color"); 378 fp_gtk_style_context_get_background_color = 379 dl_symbol("gtk_style_context_get_background_color"); 380 fp_gtk_widget_get_state_flags = dl_symbol("gtk_widget_get_state_flags"); 381 fp_gtk_style_context_set_state = 382 dl_symbol("gtk_style_context_set_state"); 383 fp_gtk_style_context_add_class = 384 dl_symbol("gtk_style_context_add_class"); 385 fp_gtk_style_context_save = dl_symbol("gtk_style_context_save"); 386 fp_gtk_style_context_restore = dl_symbol("gtk_style_context_restore"); 387 fp_gtk_render_check = dl_symbol("gtk_render_check"); 388 fp_gtk_render_option = dl_symbol("gtk_render_option"); 389 fp_gtk_render_extension = dl_symbol("gtk_render_extension"); 390 fp_gtk_render_expander = dl_symbol("gtk_render_expander"); 391 fp_gtk_render_frame_gap = dl_symbol("gtk_render_frame_gap"); 392 fp_gtk_render_line = dl_symbol("gtk_render_line"); 393 fp_gtk_widget_render_icon_pixbuf = 394 dl_symbol("gtk_widget_render_icon_pixbuf"); 395 if (fp_gtk_check_version(3, 10, 0)) { 396 gtk3_version_3_10 = FALSE; 397 } else { 398 fp_gdk_window_create_similar_image_surface = 399 dl_symbol("gdk_window_create_similar_image_surface"); 400 } 401 gtk3_version_3_14 = !fp_gtk_check_version(3, 14, 0); 402 403 fp_gdk_window_create_similar_surface = 404 dl_symbol("gdk_window_create_similar_surface"); 405 fp_gtk_settings_get_for_screen = 406 dl_symbol("gtk_settings_get_for_screen"); 407 fp_gtk_widget_get_screen = dl_symbol("gtk_widget_get_screen"); 408 fp_gtk_css_provider_get_named = dl_symbol("gtk_css_provider_get_named"); 409 fp_gtk_style_context_add_provider = 410 dl_symbol("gtk_style_context_add_provider"); 411 fp_gtk_render_frame = dl_symbol("gtk_render_frame"); 412 fp_gtk_render_focus = dl_symbol("gtk_render_focus"); 413 fp_gtk_render_handle = dl_symbol("gtk_render_handle"); 414 fp_gtk_render_arrow = dl_symbol("gtk_render_arrow"); 415 416 fp_gtk_style_context_get_property = 417 dl_symbol("gtk_style_context_get_property"); 418 fp_gtk_scrolled_window_set_shadow_type = 419 dl_symbol("gtk_scrolled_window_set_shadow_type"); 420 fp_gtk_render_slider = dl_symbol("gtk_render_slider"); 421 fp_gtk_style_context_get_padding = 422 dl_symbol("gtk_style_context_get_padding"); 423 fp_gtk_range_set_inverted = dl_symbol("gtk_range_set_inverted"); 424 fp_gtk_style_context_get_font = dl_symbol("gtk_style_context_get_font"); 425 fp_gtk_widget_get_allocated_width = 426 dl_symbol("gtk_widget_get_allocated_width"); 427 fp_gtk_widget_get_allocated_height = 428 dl_symbol("gtk_widget_get_allocated_height"); 429 fp_gtk_icon_theme_get_default = dl_symbol("gtk_icon_theme_get_default"); 430 fp_gtk_icon_theme_load_icon = dl_symbol("gtk_icon_theme_load_icon"); 431 432 fp_gtk_adjustment_set_lower = dl_symbol("gtk_adjustment_set_lower"); 433 fp_gtk_adjustment_set_page_increment = 434 dl_symbol("gtk_adjustment_set_page_increment"); 435 fp_gtk_adjustment_set_page_size = 436 dl_symbol("gtk_adjustment_set_page_size"); 437 fp_gtk_adjustment_set_step_increment = 438 dl_symbol("gtk_adjustment_set_step_increment"); 439 fp_gtk_adjustment_set_upper = dl_symbol("gtk_adjustment_set_upper"); 440 fp_gtk_adjustment_set_value = dl_symbol("gtk_adjustment_set_value"); 441 442 fp_gtk_render_activity = dl_symbol("gtk_render_activity"); 443 fp_gtk_render_background = dl_symbol("gtk_render_background"); 444 fp_gtk_style_context_has_class = 445 dl_symbol("gtk_style_context_has_class"); 446 447 fp_gtk_style_context_set_junction_sides = 448 dl_symbol("gtk_style_context_set_junction_sides"); 449 fp_gtk_style_context_add_region = 450 dl_symbol("gtk_style_context_add_region"); 451 452 fp_gtk_init_check = dl_symbol("gtk_init_check"); 453 454 /* GTK widgets */ 455 fp_gtk_arrow_new = dl_symbol("gtk_arrow_new"); 456 fp_gtk_button_new = dl_symbol("gtk_button_new"); 457 fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new"); 458 fp_gtk_check_button_new = dl_symbol("gtk_check_button_new"); 459 fp_gtk_check_menu_item_new = 460 dl_symbol("gtk_check_menu_item_new"); 461 fp_gtk_color_selection_dialog_new = 462 dl_symbol("gtk_color_selection_dialog_new"); 463 fp_gtk_entry_new = dl_symbol("gtk_entry_new"); 464 fp_gtk_fixed_new = dl_symbol("gtk_fixed_new"); 465 fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new"); 466 fp_gtk_image_new = dl_symbol("gtk_image_new"); 467 fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new"); 468 fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new"); 469 fp_gtk_scale_new = dl_symbol("gtk_scale_new"); 470 fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new"); 471 fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new"); 472 fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new"); 473 fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new"); 474 fp_gtk_label_new = dl_symbol("gtk_label_new"); 475 fp_gtk_menu_new = dl_symbol("gtk_menu_new"); 476 fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new"); 477 fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new"); 478 fp_gtk_menu_item_set_submenu = 479 dl_symbol("gtk_menu_item_set_submenu"); 480 fp_gtk_notebook_new = dl_symbol("gtk_notebook_new"); 481 fp_gtk_progress_bar_new = 482 dl_symbol("gtk_progress_bar_new"); 483 fp_gtk_progress_bar_set_orientation = 484 dl_symbol("gtk_orientable_set_orientation"); 485 fp_gtk_radio_button_new = 486 dl_symbol("gtk_radio_button_new"); 487 fp_gtk_radio_menu_item_new = 488 dl_symbol("gtk_radio_menu_item_new"); 489 fp_gtk_scrolled_window_new = 490 dl_symbol("gtk_scrolled_window_new"); 491 fp_gtk_separator_menu_item_new = 492 dl_symbol("gtk_separator_menu_item_new"); 493 fp_gtk_text_view_new = dl_symbol("gtk_text_view_new"); 494 fp_gtk_toggle_button_new = 495 dl_symbol("gtk_toggle_button_new"); 496 fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new"); 497 fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new"); 498 fp_gtk_viewport_new = dl_symbol("gtk_viewport_new"); 499 fp_gtk_window_new = dl_symbol("gtk_window_new"); 500 fp_gtk_window_present = dl_symbol("gtk_window_present"); 501 fp_gtk_window_move = dl_symbol("gtk_window_move"); 502 fp_gtk_window_resize = dl_symbol("gtk_window_resize"); 503 504 fp_gtk_dialog_new = dl_symbol("gtk_dialog_new"); 505 fp_gtk_frame_new = dl_symbol("gtk_frame_new"); 506 507 fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new"); 508 fp_gtk_container_add = dl_symbol("gtk_container_add"); 509 fp_gtk_menu_shell_append = 510 dl_symbol("gtk_menu_shell_append"); 511 fp_gtk_widget_realize = dl_symbol("gtk_widget_realize"); 512 fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy"); 513 fp_gtk_widget_render_icon = 514 dl_symbol("gtk_widget_render_icon"); 515 fp_gtk_widget_set_name = 516 dl_symbol("gtk_widget_set_name"); 517 fp_gtk_widget_set_parent = 518 dl_symbol("gtk_widget_set_parent"); 519 fp_gtk_widget_set_direction = 520 dl_symbol("gtk_widget_set_direction"); 521 fp_gtk_widget_style_get = 522 dl_symbol("gtk_widget_style_get"); 523 fp_gtk_widget_class_install_style_property = 524 dl_symbol("gtk_widget_class_install_style_property"); 525 fp_gtk_widget_class_find_style_property = 526 dl_symbol("gtk_widget_class_find_style_property"); 527 fp_gtk_widget_style_get_property = 528 dl_symbol("gtk_widget_style_get_property"); 529 fp_pango_font_description_to_string = 530 dl_symbol("pango_font_description_to_string"); 531 fp_gtk_settings_get_default = 532 dl_symbol("gtk_settings_get_default"); 533 fp_gtk_widget_get_settings = 534 dl_symbol("gtk_widget_get_settings"); 535 fp_gtk_border_get_type = dl_symbol("gtk_border_get_type"); 536 fp_gtk_arrow_set = dl_symbol("gtk_arrow_set"); 537 fp_gtk_widget_size_request = 538 dl_symbol("gtk_widget_size_request"); 539 fp_gtk_range_get_adjustment = 540 dl_symbol("gtk_range_get_adjustment"); 541 542 fp_gtk_widget_hide = dl_symbol("gtk_widget_hide"); 543 fp_gtk_main_quit = dl_symbol("gtk_main_quit"); 544 fp_g_signal_connect_data = dl_symbol("g_signal_connect_data"); 545 fp_gtk_widget_show = dl_symbol("gtk_widget_show"); 546 fp_gtk_main = dl_symbol("gtk_main"); 547 548 fp_g_path_get_dirname = dl_symbol("g_path_get_dirname"); 549 550 fp_gdk_threads_enter = dl_symbol("gdk_threads_enter"); 551 fp_gdk_threads_leave = dl_symbol("gdk_threads_leave"); 552 553 /** 554 * Functions for sun_awt_X11_GtkFileDialogPeer.c 555 */ 556 gtk3_file_chooser_load(); 557 558 fp_gtk_combo_box_new = dlsym(gtk3_libhandle, "gtk_combo_box_new"); 559 fp_gtk_combo_box_entry_new = dlsym(gtk3_libhandle, 560 "gtk_combo_box_new_with_entry"); 561 fp_gtk_separator_tool_item_new = dlsym(gtk3_libhandle, 562 "gtk_separator_tool_item_new"); 563 564 fp_g_list_append = dl_symbol("g_list_append"); 565 fp_g_list_free = dl_symbol("g_list_free"); 566 fp_g_list_free_full = dl_symbol("g_list_free_full"); 567 } 568 /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION 569 * Otherwise we can check the return value of setjmp method. 570 */ 571 else 572 { 573 dlclose(gtk3_libhandle); 574 gtk3_libhandle = NULL; 575 576 dlclose(gthread_libhandle); 577 gthread_libhandle = NULL; 578 579 return NULL; 580 } 581 582 /* 583 * Strip the AT-SPI GTK_MODULEs if present 584 */ 585 gtk_modules_env = getenv ("GTK_MODULES"); 586 if ((gtk_modules_env && strstr (gtk_modules_env, "atk-bridge")) || 587 (gtk_modules_env && strstr (gtk_modules_env, "gail"))) 588 { 589 /* the new env will be smaller than the old one */ 590 gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc, 591 sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env)); 592 593 if (new_env != NULL ) 594 { 595 /* careful, strtok modifies its args */ 596 gchar *tmp_env = strdup (gtk_modules_env); 597 strcpy(new_env, ENV_PREFIX); 598 599 /* strip out 'atk-bridge' and 'gail' */ 600 size_t PREFIX_LENGTH = strlen(ENV_PREFIX); 601 while ((s = strtok(tmp_env, ":"))) 602 { 603 if ((!strstr (s, "atk-bridge")) && (!strstr (s, "gail"))) 604 { 605 if (strlen (new_env) > PREFIX_LENGTH) { 606 new_env = strcat (new_env, ":"); 607 } 608 new_env = strcat(new_env, s); 609 } 610 if (tmp_env) 611 { 612 free (tmp_env); 613 tmp_env = NULL; /* next call to strtok arg1==NULL */ 614 } 615 } 616 putenv (new_env); 617 free (new_env); 618 free (tmp_env); 619 } 620 } 621 /* 622 * GTK should be initialized with gtk_init_check() before use. 623 * 624 * gtk_init_check installs its own error handlers. It is critical that 625 * we preserve error handler set from AWT. Otherwise we'll crash on 626 * BadMatch errors which we would normally ignore. The IO error handler 627 * is preserved here, too, just for consistency. 628 */ 629 AWT_LOCK(); 630 handler = XSetErrorHandler(NULL); 631 io_handler = XSetIOErrorHandler(NULL); 632 result = (*fp_gtk_init_check)(NULL, NULL); 633 XSetErrorHandler(handler); 634 XSetIOErrorHandler(io_handler); 635 AWT_UNLOCK(); 636 /* Initialize widget array. */ 637 for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++) 638 { 639 gtk3_widgets[i] = NULL; 640 } 641 if (result) { 642 GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi)); 643 gtk3_init(gtk); 644 return gtk; 645 } 646 return NULL; 647 } 648 649 static int gtk3_unload() 650 { 651 int i; 652 char *gtk3_error; 653 654 if (!gtk3_libhandle) 655 return TRUE; 656 657 /* Release painting objects */ 658 if (surface != NULL) { 659 fp_cairo_destroy(cr); 660 fp_cairo_surface_destroy(surface); 661 surface = NULL; 662 } 663 664 if (gtk3_window != NULL) { 665 /* Destroying toplevel widget will destroy all contained widgets */ 666 (*fp_gtk_widget_destroy)(gtk3_window); 667 668 /* Unset some static data so they get reinitialized on next load */ 669 gtk3_window = NULL; 670 } 671 672 dlerror(); 673 dlclose(gtk3_libhandle); 674 dlclose(gthread_libhandle); 675 if ((gtk3_error = dlerror()) != NULL) 676 { 677 return FALSE; 678 } 679 return TRUE; 680 } 681 682 /* Dispatch all pending events from the GTK event loop. 683 * This is needed to catch theme change and update widgets' style. 684 */ 685 static void flush_gtk_event_loop() 686 { 687 while((*fp_g_main_context_iteration)(NULL)); 688 } 689 690 /* 691 * Initialize components of containment hierarchy. This creates a GtkFixed 692 * inside a GtkWindow. All widgets get realized. 693 */ 694 static void init_containers() 695 { 696 if (gtk3_window == NULL) 697 { 698 gtk3_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); 699 gtk3_fixed = (GtkFixed *)(*fp_gtk_fixed_new)(); 700 (*fp_gtk_container_add)((GtkContainer*)gtk3_window, 701 (GtkWidget *)gtk3_fixed); 702 (*fp_gtk_widget_realize)(gtk3_window); 703 (*fp_gtk_widget_realize)((GtkWidget *)gtk3_fixed); 704 705 GtkSettings* settings = fp_gtk_settings_get_for_screen( 706 fp_gtk_widget_get_screen(gtk3_window)); 707 gchar* strval = NULL; 708 fp_g_object_get(settings, "gtk-theme-name", &strval, NULL); 709 gtk3_css = fp_gtk_css_provider_get_named(strval, NULL); 710 } 711 } 712 713 /* 714 * Ensure everything is ready for drawing an element of the specified width 715 * and height. 716 * 717 * We should somehow handle translucent images. GTK can draw to X Drawables 718 * only, which don't support alpha. When we retrieve the image back from 719 * the server, translucency information is lost. There're several ways to 720 * work around this: 721 * 1) Subclass GdkPixmap and cache translucent objects on client side. This 722 * requires us to implement parts of X server drawing logic on client side. 723 * Many X requests can potentially be "translucent"; e.g. XDrawLine with 724 * fill=tile and a translucent tile is a "translucent" operation, whereas 725 * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some 726 * do) intermix transparent and opaque operations which makes caching even 727 * more problematic. 728 * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support 729 * for it (as of version 2.6). Also even in JDS 3 Xorg does not support 730 * these visuals by default, which makes optimizing for them pointless. 731 * We can consider doing this at a later point when ARGB visuals become more 732 * popular. 733 * 3') GTK has plans to use Cairo as its graphical backend (presumably in 734 * 2.8), and Cairo supports alpha. With it we could also get rid of the 735 * unnecessary round trip to server and do all the drawing on client side. 736 * 4) For now we draw to two different pixmaps and restore alpha channel by 737 * comparing results. This can be optimized by using subclassed pixmap and 738 */ 739 static void gtk3_init_painting(JNIEnv *env, gint width, gint height) 740 { 741 init_containers(); 742 743 if (cr) { 744 fp_cairo_destroy(cr); 745 } 746 747 if (surface != NULL) { 748 /* free old stuff */ 749 fp_cairo_surface_destroy(surface); 750 751 } 752 753 if (gtk3_version_3_10) { 754 surface = fp_gdk_window_create_similar_image_surface( 755 fp_gtk_widget_get_window(gtk3_window), 756 CAIRO_FORMAT_ARGB32, width, height, 1); 757 } else { 758 surface = fp_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 759 width, height); 760 } 761 762 cr = fp_cairo_create(surface); 763 } 764 765 /* 766 * Restore image from white and black pixmaps and copy it into destination 767 * buffer. This method compares two pixbufs taken from white and black 768 * pixmaps and decodes color and alpha components. Pixbufs are RGB without 769 * alpha, destination buffer is ABGR. 770 * 771 * The return value is the transparency type of the resulting image, either 772 * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and 773 * java_awt_Transparency_TRANSLUCENT. 774 */ 775 static gint gtk3_copy_image(gint *dst, gint width, gint height) 776 { 777 gint i, j, r, g, b; 778 guchar *data; 779 gint stride, padding; 780 781 fp_cairo_surface_flush(surface); 782 data = (*fp_cairo_image_surface_get_data)(surface); 783 stride = (*fp_cairo_image_surface_get_stride)(surface); 784 padding = stride - width * 4; 785 786 for (i = 0; i < height; i++) { 787 for (j = 0; j < width; j++) { 788 int r = *data++; 789 int g = *data++; 790 int b = *data++; 791 int a = *data++; 792 *dst++ = (a << 24 | b << 16 | g << 8 | r); 793 } 794 data += padding; 795 } 796 return java_awt_Transparency_TRANSLUCENT; 797 } 798 799 static void gtk3_set_direction(GtkWidget *widget, GtkTextDirection dir) 800 { 801 /* 802 * Some engines (inexplicably) look at the direction of the widget's 803 * parent, so we need to set the direction of both the widget and its 804 * parent. 805 */ 806 (*fp_gtk_widget_set_direction)(widget, dir); 807 GtkWidget* parent = fp_gtk_widget_get_parent(widget); 808 if (parent != NULL) { 809 fp_gtk_widget_set_direction(parent, dir); 810 } 811 } 812 813 /* GTK state_type filter */ 814 static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state) 815 { 816 GtkStateType result = GTK_STATE_NORMAL; 817 818 if ((synth_state & DISABLED) != 0) { 819 result = GTK_STATE_INSENSITIVE; 820 } else if ((synth_state & PRESSED) != 0) { 821 result = GTK_STATE_ACTIVE; 822 } else if ((synth_state & MOUSE_OVER) != 0) { 823 result = GTK_STATE_PRELIGHT; 824 } 825 return result; 826 } 827 828 static GtkStateFlags get_gtk_state_flags(gint synth_state) 829 { 830 GtkStateFlags flags = 0; 831 832 if ((synth_state & DISABLED) != 0) { 833 flags |= GTK_STATE_FLAG_INSENSITIVE; 834 } 835 if (((synth_state & PRESSED) != 0 || (synth_state & SELECTED) != 0)) { 836 flags |= GTK_STATE_FLAG_ACTIVE; 837 } 838 if ((synth_state & MOUSE_OVER) != 0) { 839 flags |= GTK_STATE_FLAG_PRELIGHT; 840 } 841 if ((synth_state & FOCUSED) != 0) { 842 flags |= GTK_STATE_FLAG_FOCUSED; 843 } 844 return flags; 845 } 846 847 static GtkStateFlags get_gtk_flags(GtkStateType state_type) { 848 GtkStateFlags flags = 0; 849 switch (state_type) 850 { 851 case GTK_STATE_PRELIGHT: 852 flags |= GTK_STATE_FLAG_PRELIGHT; 853 break; 854 case GTK_STATE_SELECTED: 855 flags |= GTK_STATE_FLAG_SELECTED; 856 break; 857 case GTK_STATE_INSENSITIVE: 858 flags |= GTK_STATE_FLAG_INSENSITIVE; 859 break; 860 case GTK_STATE_ACTIVE: 861 flags |= GTK_STATE_FLAG_ACTIVE; 862 break; 863 case GTK_STATE_FOCUSED: 864 flags |= GTK_STATE_FLAG_FOCUSED; 865 break; 866 default: 867 break; 868 } 869 return flags; 870 } 871 872 /* GTK shadow_type filter */ 873 static GtkShadowType get_gtk_shadow_type(WidgetType widget_type, 874 gint synth_state) 875 { 876 GtkShadowType result = GTK_SHADOW_OUT; 877 878 if ((synth_state & SELECTED) != 0) { 879 result = GTK_SHADOW_IN; 880 } 881 return result; 882 } 883 884 885 static GtkWidget* gtk3_get_arrow(GtkArrowType arrow_type, 886 GtkShadowType shadow_type) 887 { 888 GtkWidget *arrow = NULL; 889 if (NULL == gtk3_widgets[_GTK_ARROW_TYPE]) 890 { 891 gtk3_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type, 892 shadow_type); 893 (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed, 894 gtk3_widgets[_GTK_ARROW_TYPE]); 895 (*fp_gtk_widget_realize)(gtk3_widgets[_GTK_ARROW_TYPE]); 896 } 897 arrow = gtk3_widgets[_GTK_ARROW_TYPE]; 898 899 (*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type); 900 return arrow; 901 } 902 903 static GtkAdjustment* create_adjustment() 904 { 905 return (GtkAdjustment *) 906 (*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0); 907 } 908 909 /** 910 * Returns a pointer to the cached native widget for the specified widget 911 * type. 912 */ 913 static GtkWidget *gtk3_get_widget(WidgetType widget_type) 914 { 915 gboolean init_result = FALSE; 916 GtkWidget *result = NULL; 917 switch (widget_type) 918 { 919 case BUTTON: 920 case TABLE_HEADER: 921 if ((init_result = (NULL == gtk3_widgets[_GTK_BUTTON_TYPE]))) 922 { 923 gtk3_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)(); 924 } 925 result = gtk3_widgets[_GTK_BUTTON_TYPE]; 926 break; 927 case CHECK_BOX: 928 if ((init_result = (NULL == gtk3_widgets[_GTK_CHECK_BUTTON_TYPE]))) 929 { 930 gtk3_widgets[_GTK_CHECK_BUTTON_TYPE] = 931 (*fp_gtk_check_button_new)(); 932 } 933 result = gtk3_widgets[_GTK_CHECK_BUTTON_TYPE]; 934 break; 935 case CHECK_BOX_MENU_ITEM: 936 if ((init_result = (NULL == gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE]))) 937 { 938 gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE] = 939 (*fp_gtk_check_menu_item_new)(); 940 } 941 result = gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE]; 942 break; 943 /************************************************************ 944 * Creation a dedicated color chooser is dangerous because 945 * it deadlocks the EDT 946 ************************************************************/ 947 /* case COLOR_CHOOSER: 948 if (init_result = 949 (NULL == gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE])) 950 { 951 gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] = 952 (*fp_gtk_color_selection_dialog_new)(NULL); 953 } 954 result = gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]; 955 break;*/ 956 case COMBO_BOX: 957 if ((init_result = (NULL == gtk3_widgets[_GTK_COMBO_BOX_TYPE]))) 958 { 959 gtk3_widgets[_GTK_COMBO_BOX_TYPE] = 960 (*fp_gtk_combo_box_new)(); 961 } 962 result = gtk3_widgets[_GTK_COMBO_BOX_TYPE]; 963 break; 964 case COMBO_BOX_ARROW_BUTTON: 965 if ((init_result = 966 (NULL == gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]))) 967 { 968 gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] = 969 (*fp_gtk_toggle_button_new)(); 970 } 971 result = gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]; 972 break; 973 case COMBO_BOX_TEXT_FIELD: 974 if ((init_result = 975 (NULL == gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]))) 976 { 977 result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] = 978 (*fp_gtk_entry_new)(); 979 } 980 result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]; 981 break; 982 case DESKTOP_ICON: 983 case INTERNAL_FRAME_TITLE_PANE: 984 case LABEL: 985 if ((init_result = (NULL == gtk3_widgets[_GTK_LABEL_TYPE]))) 986 { 987 gtk3_widgets[_GTK_LABEL_TYPE] = 988 (*fp_gtk_label_new)(NULL); 989 } 990 result = gtk3_widgets[_GTK_LABEL_TYPE]; 991 break; 992 case DESKTOP_PANE: 993 case PANEL: 994 case ROOT_PANE: 995 if ((init_result = (NULL == gtk3_widgets[_GTK_CONTAINER_TYPE]))) 996 { 997 /* There is no constructor for a container type. I've 998 * chosen GtkFixed container since it has a default 999 * constructor. 1000 */ 1001 gtk3_widgets[_GTK_CONTAINER_TYPE] = 1002 (*fp_gtk_fixed_new)(); 1003 } 1004 result = gtk3_widgets[_GTK_CONTAINER_TYPE]; 1005 break; 1006 case EDITOR_PANE: 1007 case TEXT_AREA: 1008 case TEXT_PANE: 1009 if ((init_result = (NULL == gtk3_widgets[_GTK_TEXT_VIEW_TYPE]))) 1010 { 1011 gtk3_widgets[_GTK_TEXT_VIEW_TYPE] = 1012 (*fp_gtk_text_view_new)(); 1013 } 1014 result = gtk3_widgets[_GTK_TEXT_VIEW_TYPE]; 1015 break; 1016 case FORMATTED_TEXT_FIELD: 1017 case PASSWORD_FIELD: 1018 case TEXT_FIELD: 1019 if ((init_result = (NULL == gtk3_widgets[_GTK_ENTRY_TYPE]))) 1020 { 1021 gtk3_widgets[_GTK_ENTRY_TYPE] = 1022 (*fp_gtk_entry_new)(); 1023 } 1024 result = gtk3_widgets[_GTK_ENTRY_TYPE]; 1025 break; 1026 case HANDLE_BOX: 1027 if ((init_result = (NULL == gtk3_widgets[_GTK_HANDLE_BOX_TYPE]))) 1028 { 1029 gtk3_widgets[_GTK_HANDLE_BOX_TYPE] = 1030 (*fp_gtk_handle_box_new)(); 1031 } 1032 result = gtk3_widgets[_GTK_HANDLE_BOX_TYPE]; 1033 break; 1034 case HSCROLL_BAR: 1035 case HSCROLL_BAR_BUTTON_LEFT: 1036 case HSCROLL_BAR_BUTTON_RIGHT: 1037 case HSCROLL_BAR_TRACK: 1038 case HSCROLL_BAR_THUMB: 1039 if ((init_result = (NULL == gtk3_widgets[_GTK_HSCROLLBAR_TYPE]))) 1040 { 1041 gtk3_widgets[_GTK_HSCROLLBAR_TYPE] = 1042 (*fp_gtk_hscrollbar_new)(create_adjustment()); 1043 } 1044 result = gtk3_widgets[_GTK_HSCROLLBAR_TYPE]; 1045 break; 1046 case HSEPARATOR: 1047 if ((init_result = (NULL == gtk3_widgets[_GTK_HSEPARATOR_TYPE]))) 1048 { 1049 gtk3_widgets[_GTK_HSEPARATOR_TYPE] = 1050 (*fp_gtk_hseparator_new)(); 1051 } 1052 result = gtk3_widgets[_GTK_HSEPARATOR_TYPE]; 1053 break; 1054 case HSLIDER: 1055 case HSLIDER_THUMB: 1056 case HSLIDER_TRACK: 1057 if ((init_result = (NULL == gtk3_widgets[_GTK_HSCALE_TYPE]))) 1058 { 1059 gtk3_widgets[_GTK_HSCALE_TYPE] = 1060 (*fp_gtk_scale_new)(GTK_ORIENTATION_HORIZONTAL, NULL); 1061 } 1062 result = gtk3_widgets[_GTK_HSCALE_TYPE]; 1063 break; 1064 case HSPLIT_PANE_DIVIDER: 1065 case SPLIT_PANE: 1066 if ((init_result = (NULL == gtk3_widgets[_GTK_HPANED_TYPE]))) 1067 { 1068 gtk3_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)(); 1069 } 1070 result = gtk3_widgets[_GTK_HPANED_TYPE]; 1071 break; 1072 case IMAGE: 1073 if ((init_result = (NULL == gtk3_widgets[_GTK_IMAGE_TYPE]))) 1074 { 1075 gtk3_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)(); 1076 } 1077 result = gtk3_widgets[_GTK_IMAGE_TYPE]; 1078 break; 1079 case INTERNAL_FRAME: 1080 if ((init_result = (NULL == gtk3_widgets[_GTK_WINDOW_TYPE]))) 1081 { 1082 gtk3_widgets[_GTK_WINDOW_TYPE] = 1083 (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); 1084 } 1085 result = gtk3_widgets[_GTK_WINDOW_TYPE]; 1086 break; 1087 case TOOL_TIP: 1088 if ((init_result = (NULL == gtk3_widgets[_GTK_TOOLTIP_TYPE]))) 1089 { 1090 result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); 1091 gtk3_widgets[_GTK_TOOLTIP_TYPE] = result; 1092 } 1093 result = gtk3_widgets[_GTK_TOOLTIP_TYPE]; 1094 break; 1095 case LIST: 1096 case TABLE: 1097 case TREE: 1098 case TREE_CELL: 1099 if ((init_result = (NULL == gtk3_widgets[_GTK_TREE_VIEW_TYPE]))) 1100 { 1101 gtk3_widgets[_GTK_TREE_VIEW_TYPE] = 1102 (*fp_gtk_tree_view_new)(); 1103 } 1104 result = gtk3_widgets[_GTK_TREE_VIEW_TYPE]; 1105 break; 1106 case TITLED_BORDER: 1107 if ((init_result = (NULL == gtk3_widgets[_GTK_FRAME_TYPE]))) 1108 { 1109 gtk3_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL); 1110 } 1111 result = gtk3_widgets[_GTK_FRAME_TYPE]; 1112 break; 1113 case POPUP_MENU: 1114 if ((init_result = (NULL == gtk3_widgets[_GTK_MENU_TYPE]))) 1115 { 1116 gtk3_widgets[_GTK_MENU_TYPE] = 1117 (*fp_gtk_menu_new)(); 1118 } 1119 result = gtk3_widgets[_GTK_MENU_TYPE]; 1120 break; 1121 case MENU: 1122 case MENU_ITEM: 1123 case MENU_ITEM_ACCELERATOR: 1124 if ((init_result = (NULL == gtk3_widgets[_GTK_MENU_ITEM_TYPE]))) 1125 { 1126 gtk3_widgets[_GTK_MENU_ITEM_TYPE] = 1127 (*fp_gtk_menu_item_new)(); 1128 } 1129 result = gtk3_widgets[_GTK_MENU_ITEM_TYPE]; 1130 break; 1131 case MENU_BAR: 1132 if ((init_result = (NULL == gtk3_widgets[_GTK_MENU_BAR_TYPE]))) 1133 { 1134 gtk3_widgets[_GTK_MENU_BAR_TYPE] = 1135 (*fp_gtk_menu_bar_new)(); 1136 } 1137 result = gtk3_widgets[_GTK_MENU_BAR_TYPE]; 1138 break; 1139 case COLOR_CHOOSER: 1140 case OPTION_PANE: 1141 if ((init_result = (NULL == gtk3_widgets[_GTK_DIALOG_TYPE]))) 1142 { 1143 gtk3_widgets[_GTK_DIALOG_TYPE] = 1144 (*fp_gtk_dialog_new)(); 1145 } 1146 result = gtk3_widgets[_GTK_DIALOG_TYPE]; 1147 break; 1148 case POPUP_MENU_SEPARATOR: 1149 if ((init_result = 1150 (NULL == gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]))) 1151 { 1152 gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] = 1153 (*fp_gtk_separator_menu_item_new)(); 1154 } 1155 result = gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]; 1156 break; 1157 case HPROGRESS_BAR: 1158 if ((init_result = (NULL == gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE]))) 1159 { 1160 gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE] = 1161 (*fp_gtk_progress_bar_new)(); 1162 } 1163 result = gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE]; 1164 break; 1165 case VPROGRESS_BAR: 1166 if ((init_result = (NULL == gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE]))) 1167 { 1168 gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE] = 1169 (*fp_gtk_progress_bar_new)(); 1170 /* 1171 * Vertical JProgressBars always go bottom-to-top, 1172 * regardless of the ComponentOrientation. 1173 */ 1174 (*fp_gtk_progress_bar_set_orientation)( 1175 (GtkProgressBar *)gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE], 1176 GTK_PROGRESS_BOTTOM_TO_TOP); 1177 } 1178 result = gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE]; 1179 break; 1180 case RADIO_BUTTON: 1181 if ((init_result = (NULL == gtk3_widgets[_GTK_RADIO_BUTTON_TYPE]))) 1182 { 1183 gtk3_widgets[_GTK_RADIO_BUTTON_TYPE] = 1184 (*fp_gtk_radio_button_new)(NULL); 1185 } 1186 result = gtk3_widgets[_GTK_RADIO_BUTTON_TYPE]; 1187 break; 1188 case RADIO_BUTTON_MENU_ITEM: 1189 if ((init_result = 1190 (NULL == gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE]))) 1191 { 1192 gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE] = 1193 (*fp_gtk_radio_menu_item_new)(NULL); 1194 } 1195 result = gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE]; 1196 break; 1197 case SCROLL_PANE: 1198 if ((init_result = 1199 (NULL == gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE]))) 1200 { 1201 gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE] = 1202 (*fp_gtk_scrolled_window_new)(NULL, NULL); 1203 } 1204 result = gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE]; 1205 break; 1206 case SPINNER: 1207 case SPINNER_ARROW_BUTTON: 1208 case SPINNER_TEXT_FIELD: 1209 if ((init_result = (NULL == gtk3_widgets[_GTK_SPIN_BUTTON_TYPE]))) 1210 { 1211 result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE] = 1212 (*fp_gtk_spin_button_new)(NULL, 0, 0); 1213 } 1214 result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE]; 1215 break; 1216 case TABBED_PANE: 1217 case TABBED_PANE_TAB_AREA: 1218 case TABBED_PANE_CONTENT: 1219 case TABBED_PANE_TAB: 1220 if ((init_result = (NULL == gtk3_widgets[_GTK_NOTEBOOK_TYPE]))) 1221 { 1222 gtk3_widgets[_GTK_NOTEBOOK_TYPE] = 1223 (*fp_gtk_notebook_new)(NULL); 1224 } 1225 result = gtk3_widgets[_GTK_NOTEBOOK_TYPE]; 1226 break; 1227 case TOGGLE_BUTTON: 1228 if ((init_result = (NULL == gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE]))) 1229 { 1230 gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE] = 1231 (*fp_gtk_toggle_button_new)(NULL); 1232 } 1233 result = gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE]; 1234 break; 1235 case TOOL_BAR: 1236 case TOOL_BAR_DRAG_WINDOW: 1237 if ((init_result = (NULL == gtk3_widgets[_GTK_TOOLBAR_TYPE]))) 1238 { 1239 gtk3_widgets[_GTK_TOOLBAR_TYPE] = 1240 (*fp_gtk_toolbar_new)(NULL); 1241 } 1242 result = gtk3_widgets[_GTK_TOOLBAR_TYPE]; 1243 break; 1244 case TOOL_BAR_SEPARATOR: 1245 if ((init_result = 1246 (NULL == gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]))) 1247 { 1248 gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] = 1249 (*fp_gtk_separator_tool_item_new)(); 1250 } 1251 result = gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]; 1252 break; 1253 case VIEWPORT: 1254 if ((init_result = (NULL == gtk3_widgets[_GTK_VIEWPORT_TYPE]))) 1255 { 1256 GtkAdjustment *adjustment = create_adjustment(); 1257 gtk3_widgets[_GTK_VIEWPORT_TYPE] = 1258 (*fp_gtk_viewport_new)(adjustment, adjustment); 1259 } 1260 result = gtk3_widgets[_GTK_VIEWPORT_TYPE]; 1261 break; 1262 case VSCROLL_BAR: 1263 case VSCROLL_BAR_BUTTON_UP: 1264 case VSCROLL_BAR_BUTTON_DOWN: 1265 case VSCROLL_BAR_TRACK: 1266 case VSCROLL_BAR_THUMB: 1267 if ((init_result = (NULL == gtk3_widgets[_GTK_VSCROLLBAR_TYPE]))) 1268 { 1269 gtk3_widgets[_GTK_VSCROLLBAR_TYPE] = 1270 (*fp_gtk_vscrollbar_new)(create_adjustment()); 1271 } 1272 result = gtk3_widgets[_GTK_VSCROLLBAR_TYPE]; 1273 break; 1274 case VSEPARATOR: 1275 if ((init_result = (NULL == gtk3_widgets[_GTK_VSEPARATOR_TYPE]))) 1276 { 1277 gtk3_widgets[_GTK_VSEPARATOR_TYPE] = 1278 (*fp_gtk_vseparator_new)(); 1279 } 1280 result = gtk3_widgets[_GTK_VSEPARATOR_TYPE]; 1281 break; 1282 case VSLIDER: 1283 case VSLIDER_THUMB: 1284 case VSLIDER_TRACK: 1285 if ((init_result = (NULL == gtk3_widgets[_GTK_VSCALE_TYPE]))) 1286 { 1287 gtk3_widgets[_GTK_VSCALE_TYPE] = 1288 (*fp_gtk_scale_new)(GTK_ORIENTATION_VERTICAL, NULL); 1289 } 1290 result = gtk3_widgets[_GTK_VSCALE_TYPE]; 1291 /* 1292 * Vertical JSliders start at the bottom, while vertical 1293 * GtkVScale widgets start at the top (by default), so to fix 1294 * this we set the "inverted" flag to get the Swing behavior. 1295 */ 1296 fp_gtk_range_set_inverted((GtkRange*)result, TRUE); 1297 break; 1298 case VSPLIT_PANE_DIVIDER: 1299 if ((init_result = (NULL == gtk3_widgets[_GTK_VPANED_TYPE]))) 1300 { 1301 gtk3_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)(); 1302 } 1303 result = gtk3_widgets[_GTK_VPANED_TYPE]; 1304 break; 1305 default: 1306 result = NULL; 1307 break; 1308 } 1309 1310 if (result != NULL && init_result) 1311 { 1312 if (widget_type == RADIO_BUTTON_MENU_ITEM || 1313 widget_type == CHECK_BOX_MENU_ITEM || 1314 widget_type == MENU_ITEM || 1315 widget_type == MENU || 1316 widget_type == POPUP_MENU_SEPARATOR) 1317 { 1318 GtkWidget *menu = gtk3_get_widget(POPUP_MENU); 1319 (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result); 1320 } 1321 else if (widget_type == POPUP_MENU) 1322 { 1323 GtkWidget *menu_bar = gtk3_get_widget(MENU_BAR); 1324 GtkWidget *root_menu = (*fp_gtk_menu_item_new)(); 1325 (*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result); 1326 (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu); 1327 } 1328 else if (widget_type == COMBO_BOX_TEXT_FIELD ) 1329 { 1330 GtkWidget* combo = gtk3_get_widget(COMBO_BOX); 1331 1332 /* 1333 * We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry 1334 * in order to trick engines into thinking it's a real combobox 1335 * arrow button/text field. 1336 */ 1337 1338 fp_gtk_container_add ((GtkContainer*)(combo), result); 1339 GtkStyleContext* context = fp_gtk_widget_get_style_context (combo); 1340 fp_gtk_style_context_add_class (context, "combobox-entry"); 1341 context = fp_gtk_widget_get_style_context (result); 1342 fp_gtk_style_context_add_class (context, "combobox"); 1343 fp_gtk_style_context_add_class (context, "entry"); 1344 } 1345 else if (widget_type == COMBO_BOX_ARROW_BUTTON ) 1346 { 1347 GtkWidget* combo = gtk3_get_widget(COMBO_BOX); 1348 fp_gtk_widget_set_parent(result, combo); 1349 } 1350 else if (widget_type != TOOL_TIP && 1351 widget_type != INTERNAL_FRAME && 1352 widget_type != OPTION_PANE) 1353 { 1354 (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed, result); 1355 } 1356 (*fp_gtk_widget_realize)(result); 1357 } 1358 return result; 1359 } 1360 1361 static void gtk3_paint_arrow(WidgetType widget_type, GtkStateType state_type, 1362 GtkShadowType shadow_type, const gchar *detail, 1363 gint x, gint y, gint width, gint height, 1364 GtkArrowType arrow_type, gboolean fill) 1365 { 1366 gdouble xx, yy, a = G_PI; 1367 int s = width; 1368 gtk3_widget = gtk3_get_arrow(arrow_type, shadow_type); 1369 1370 switch (widget_type) 1371 { 1372 case SPINNER_ARROW_BUTTON: 1373 s = (int)(0.4 * width + 0.5) + 1; 1374 if (arrow_type == GTK_ARROW_UP) { 1375 a = 0; 1376 } else if (arrow_type == GTK_ARROW_DOWN) { 1377 a = G_PI; 1378 } 1379 break; 1380 1381 case HSCROLL_BAR_BUTTON_LEFT: 1382 s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1; 1383 a = 3 * G_PI / 2; 1384 break; 1385 1386 case HSCROLL_BAR_BUTTON_RIGHT: 1387 s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1; 1388 a = G_PI / 2; 1389 break; 1390 1391 case VSCROLL_BAR_BUTTON_UP: 1392 s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1; 1393 a = 0; 1394 break; 1395 1396 case VSCROLL_BAR_BUTTON_DOWN: 1397 s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1; 1398 a = G_PI; 1399 break; 1400 1401 case COMBO_BOX_ARROW_BUTTON: 1402 s = (int)(0.3 * height + 0.5) + 1; 1403 a = G_PI; 1404 break; 1405 1406 case TABLE: 1407 s = (int)(0.8 * height + 0.5) + 1; 1408 if (arrow_type == GTK_ARROW_UP) { 1409 a = G_PI; 1410 } else if (arrow_type == GTK_ARROW_DOWN) { 1411 a = 0; 1412 } 1413 break; 1414 1415 case MENU_ITEM: 1416 if (arrow_type == GTK_ARROW_UP) { 1417 a = G_PI; 1418 } else if (arrow_type == GTK_ARROW_DOWN) { 1419 a = 0; 1420 } else if (arrow_type == GTK_ARROW_RIGHT) { 1421 a = G_PI / 2; 1422 } else if (arrow_type == GTK_ARROW_LEFT) { 1423 a = 3 * G_PI / 2; 1424 } 1425 break; 1426 1427 default: 1428 if (arrow_type == GTK_ARROW_UP) { 1429 a = G_PI; 1430 } else if (arrow_type == GTK_ARROW_DOWN) { 1431 a = 0; 1432 } else if (arrow_type == GTK_ARROW_RIGHT) { 1433 a = G_PI / 2; 1434 } else if (arrow_type == GTK_ARROW_LEFT) { 1435 a = 3 * G_PI / 2; 1436 } 1437 break; 1438 } 1439 1440 if (s < width && s < height) { 1441 xx = x + (0.5 * (width - s) + 0.5); 1442 yy = y + (0.5 * (height - s) + 0.5); 1443 } else { 1444 xx = x; 1445 yy = y; 1446 } 1447 1448 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1449 fp_gtk_style_context_save (context); 1450 1451 1452 if (detail != NULL) { 1453 transform_detail_string(detail, context); 1454 } 1455 1456 GtkStateFlags flags = get_gtk_flags(state_type); 1457 1458 fp_gtk_style_context_set_state (context, flags); 1459 1460 (*fp_gtk_render_arrow)(context, cr, a, xx, yy, s); 1461 1462 fp_gtk_style_context_restore (context); 1463 } 1464 1465 static void gtk3_paint_box(WidgetType widget_type, GtkStateType state_type, 1466 GtkShadowType shadow_type, const gchar *detail, 1467 gint x, gint y, gint width, gint height, 1468 gint synth_state, GtkTextDirection dir) 1469 { 1470 gtk3_widget = gtk3_get_widget(widget_type); 1471 1472 if (widget_type == HSLIDER_TRACK) { 1473 /* 1474 * For horizontal JSliders with right-to-left orientation, we need 1475 * to set the "inverted" flag to match the native GTK behavior where 1476 * the foreground highlight is on the right side of the slider thumb. 1477 * This is needed especially for the ubuntulooks engine, which looks 1478 * exclusively at the "inverted" flag to determine on which side of 1479 * the thumb to paint the highlight... 1480 */ 1481 fp_gtk_range_set_inverted((GtkRange*)gtk3_widget, dir == 1482 GTK_TEXT_DIR_RTL); 1483 1484 /* 1485 * Note however that other engines like clearlooks will look at both 1486 * the "inverted" field and the text direction to determine how 1487 * the foreground highlight is painted: 1488 * !inverted && ltr --> paint highlight on left side 1489 * !inverted && rtl --> paint highlight on right side 1490 * inverted && ltr --> paint highlight on right side 1491 * inverted && rtl --> paint highlight on left side 1492 * So the only way to reliably get the desired results for horizontal 1493 * JSlider (i.e., highlight on left side for LTR ComponentOrientation 1494 * and highlight on right side for RTL ComponentOrientation) is to 1495 * always override text direction as LTR, and then set the "inverted" 1496 * flag accordingly (as we have done above). 1497 */ 1498 dir = GTK_TEXT_DIR_LTR; 1499 } 1500 1501 /* 1502 * Some engines (e.g. clearlooks) will paint the shadow of certain 1503 * widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the 1504 * the text direction. 1505 */ 1506 gtk3_set_direction(gtk3_widget, dir); 1507 1508 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1509 fp_gtk_style_context_save (context); 1510 1511 transform_detail_string(detail, context); 1512 1513 GtkStateFlags flags = get_gtk_flags(state_type); 1514 1515 if (shadow_type == GTK_SHADOW_IN && widget_type != COMBO_BOX_ARROW_BUTTON) { 1516 flags |= GTK_STATE_FLAG_ACTIVE; 1517 } 1518 1519 if (synth_state & MOUSE_OVER) { 1520 flags |= GTK_STATE_FLAG_PRELIGHT; 1521 } 1522 1523 if (synth_state & FOCUSED) { 1524 flags |= GTK_STATE_FLAG_FOCUSED; 1525 } 1526 1527 if (synth_state & DEFAULT) { 1528 fp_gtk_style_context_add_class (context, "default"); 1529 } 1530 1531 fp_gtk_style_context_set_state (context, flags); 1532 1533 if (fp_gtk_style_context_has_class(context, "progressbar")) { 1534 fp_gtk_render_activity (context, cr, x, y, width, height); 1535 } else { 1536 fp_gtk_render_background (context, cr, x, y, width, height); 1537 if (shadow_type != GTK_SHADOW_NONE) { 1538 fp_gtk_render_frame(context, cr, x, y, width, height); 1539 } 1540 } 1541 1542 fp_gtk_style_context_restore (context); 1543 /* 1544 * Reset the text direction to the default value so that we don't 1545 * accidentally affect other operations and widgets. 1546 */ 1547 gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR); 1548 } 1549 1550 static void gtk3_paint_box_gap(WidgetType widget_type, GtkStateType state_type, 1551 GtkShadowType shadow_type, const gchar *detail, 1552 gint x, gint y, gint width, gint height, 1553 GtkPositionType gap_side, gint gap_x, gint gap_width) 1554 { 1555 gtk3_widget = gtk3_get_widget(widget_type); 1556 1557 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1558 1559 fp_gtk_style_context_save (context); 1560 1561 GtkStateFlags flags = get_gtk_flags(state_type); 1562 fp_gtk_style_context_set_state(context, flags); 1563 1564 if (detail != 0) { 1565 transform_detail_string(detail, context); 1566 } 1567 fp_gtk_render_background(context, cr, x, y, width, height); 1568 1569 if (shadow_type != GTK_SHADOW_NONE) { 1570 fp_gtk_render_frame_gap(context, cr, x, y, width, height, gap_side, 1571 (gdouble)gap_x, (gdouble)gap_x + gap_width); 1572 } 1573 fp_gtk_style_context_restore (context); 1574 } 1575 1576 static void gtk3_paint_check(WidgetType widget_type, gint synth_state, 1577 const gchar *detail, gint x, gint y, gint width, gint height) 1578 { 1579 gtk3_widget = gtk3_get_widget(widget_type); 1580 1581 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1582 1583 fp_gtk_style_context_save (context); 1584 1585 GtkStateFlags flags = get_gtk_state_flags(synth_state); 1586 if (gtk3_version_3_14 && (synth_state & SELECTED)) { 1587 flags = GTK_STATE_FLAG_CHECKED; 1588 } 1589 fp_gtk_style_context_set_state(context, flags); 1590 1591 fp_gtk_style_context_add_class (context, "check"); 1592 1593 fp_gtk_render_check (context, cr, x, y, width, height); 1594 1595 fp_gtk_style_context_restore (context); 1596 } 1597 1598 1599 static void gtk3_paint_expander(WidgetType widget_type, GtkStateType state_type, 1600 const gchar *detail, gint x, gint y, gint width, gint height, 1601 GtkExpanderStyle expander_style) 1602 { 1603 gtk3_widget = gtk3_get_widget(widget_type); 1604 1605 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1606 1607 fp_gtk_style_context_save (context); 1608 1609 GtkStateFlags flags = get_gtk_flags(state_type); 1610 if (expander_style == GTK_EXPANDER_EXPANDED) { 1611 flags |= GTK_STATE_FLAG_ACTIVE; 1612 } 1613 1614 fp_gtk_style_context_set_state(context, flags); 1615 1616 if (detail != 0) { 1617 transform_detail_string(detail, context); 1618 } 1619 1620 fp_gtk_render_expander (context, cr, x + 2, y + 2, width - 4, height - 4); 1621 1622 fp_gtk_style_context_restore (context); 1623 } 1624 1625 static void gtk3_paint_extension(WidgetType widget_type, GtkStateType state_type, 1626 GtkShadowType shadow_type, const gchar *detail, 1627 gint x, gint y, gint width, gint height, GtkPositionType gap_side) 1628 { 1629 gtk3_widget = gtk3_get_widget(widget_type); 1630 1631 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1632 1633 fp_gtk_style_context_save (context); 1634 1635 GtkStateFlags flags = GTK_STATE_FLAG_NORMAL; 1636 1637 if (state_type == 0) { 1638 flags = GTK_STATE_FLAG_ACTIVE; 1639 } 1640 1641 fp_gtk_style_context_set_state(context, flags); 1642 1643 if (detail != 0) { 1644 transform_detail_string(detail, context); 1645 } 1646 switch(gap_side) { 1647 case GTK_POS_LEFT: 1648 fp_gtk_style_context_add_class(context, "right"); 1649 break; 1650 case GTK_POS_RIGHT: 1651 fp_gtk_style_context_add_class(context, "left"); 1652 break; 1653 case GTK_POS_TOP: 1654 fp_gtk_style_context_add_class(context, "bottom"); 1655 break; 1656 case GTK_POS_BOTTOM: 1657 fp_gtk_style_context_add_class(context, "top"); 1658 break; 1659 default: 1660 break; 1661 } 1662 1663 fp_gtk_render_extension(context, cr, x, y, width, height, gap_side); 1664 1665 fp_gtk_style_context_restore (context); 1666 } 1667 1668 static void gtk3_paint_flat_box(WidgetType widget_type, GtkStateType state_type, 1669 GtkShadowType shadow_type, const gchar *detail, 1670 gint x, gint y, gint width, gint height, gboolean has_focus) 1671 { 1672 if (state_type == GTK_STATE_PRELIGHT && 1673 (widget_type == CHECK_BOX || widget_type == RADIO_BUTTON)) { 1674 return; 1675 } 1676 gtk3_widget = gtk3_get_widget(widget_type); 1677 1678 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1679 1680 fp_gtk_style_context_save (context); 1681 1682 if (detail != 0) { 1683 transform_detail_string(detail, context); 1684 } 1685 1686 GtkStateFlags flags = get_gtk_flags(state_type); 1687 1688 if (has_focus) { 1689 flags |= GTK_STATE_FLAG_FOCUSED; 1690 } 1691 1692 fp_gtk_style_context_set_state (context, flags); 1693 1694 if (widget_type == COMBO_BOX_TEXT_FIELD) { 1695 width += height /2; 1696 } 1697 1698 fp_gtk_render_background (context, cr, x, y, width, height); 1699 1700 fp_gtk_style_context_restore (context); 1701 } 1702 1703 static void gtk3_paint_focus(WidgetType widget_type, GtkStateType state_type, 1704 const char *detail, gint x, gint y, gint width, gint height) 1705 { 1706 gtk3_widget = gtk3_get_widget(widget_type); 1707 1708 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1709 fp_gtk_style_context_save (context); 1710 1711 transform_detail_string(detail, context); 1712 fp_gtk_render_focus (context, cr, x, y, width, height); 1713 1714 fp_gtk_style_context_restore (context); 1715 1716 } 1717 1718 static void gtk3_paint_handle(WidgetType widget_type, GtkStateType state_type, 1719 GtkShadowType shadow_type, const gchar *detail, 1720 gint x, gint y, gint width, gint height, GtkOrientation orientation) 1721 { 1722 gtk3_widget = gtk3_get_widget(widget_type); 1723 1724 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1725 1726 fp_gtk_style_context_save (context); 1727 1728 GtkStateFlags flags = get_gtk_flags(state_type); 1729 fp_gtk_style_context_set_state(context, GTK_STATE_FLAG_PRELIGHT); 1730 1731 if (detail != 0) { 1732 transform_detail_string(detail, context); 1733 fp_gtk_style_context_add_class (context, "handlebox_bin"); 1734 } 1735 1736 fp_gtk_render_handle(context, cr, x, y, width, height); 1737 fp_gtk_render_background(context, cr, x, y, width, height); 1738 1739 fp_gtk_style_context_restore (context); 1740 } 1741 1742 static void gtk3_paint_hline(WidgetType widget_type, GtkStateType state_type, 1743 const gchar *detail, gint x, gint y, gint width, gint height) 1744 { 1745 gtk3_widget = gtk3_get_widget(widget_type); 1746 1747 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1748 1749 fp_gtk_style_context_save (context); 1750 1751 if (detail != 0) { 1752 transform_detail_string(detail, context); 1753 } 1754 1755 fp_gtk_render_line(context, cr, x, y, x + width, y); 1756 1757 fp_gtk_style_context_restore (context); 1758 } 1759 1760 static void gtk3_paint_vline(WidgetType widget_type, GtkStateType state_type, 1761 const gchar *detail, gint x, gint y, gint width, gint height) 1762 { 1763 gtk3_widget = gtk3_get_widget(widget_type); 1764 1765 1766 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1767 1768 fp_gtk_style_context_save (context); 1769 1770 if (detail != 0) { 1771 transform_detail_string(detail, context); 1772 } 1773 1774 fp_gtk_render_line(context, cr, x, y, x, y + height); 1775 1776 fp_gtk_style_context_restore (context); 1777 } 1778 1779 static void gtk3_paint_option(WidgetType widget_type, gint synth_state, 1780 const gchar *detail, gint x, gint y, gint width, gint height) 1781 { 1782 gtk3_widget = gtk3_get_widget(widget_type); 1783 1784 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1785 1786 fp_gtk_style_context_save (context); 1787 1788 GtkStateFlags flags = get_gtk_state_flags(synth_state); 1789 if (gtk3_version_3_14 && (synth_state & SELECTED)) { 1790 flags = GTK_STATE_FLAG_CHECKED; 1791 } 1792 fp_gtk_style_context_set_state(context, flags); 1793 1794 if (detail != 0) { 1795 transform_detail_string(detail, context); 1796 } 1797 1798 fp_gtk_render_option(context, cr, x, y, width, height); 1799 1800 fp_gtk_style_context_restore (context); 1801 } 1802 1803 static void gtk3_paint_shadow(WidgetType widget_type, GtkStateType state_type, 1804 GtkShadowType shadow_type, const gchar *detail, 1805 gint x, gint y, gint width, gint height, 1806 gint synth_state, GtkTextDirection dir) 1807 { 1808 if (shadow_type == GTK_SHADOW_NONE) { 1809 return; 1810 } 1811 gtk3_widget = gtk3_get_widget(widget_type); 1812 1813 /* 1814 * Some engines (e.g. clearlooks) will paint the shadow of certain 1815 * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the 1816 * the text direction. 1817 */ 1818 gtk3_set_direction(gtk3_widget, dir); 1819 1820 1821 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1822 fp_gtk_style_context_save (context); 1823 1824 if (detail) { 1825 transform_detail_string(detail, context); 1826 } 1827 1828 GtkStateFlags flags = get_gtk_flags(state_type); 1829 1830 if (synth_state & MOUSE_OVER) { 1831 flags |= GTK_STATE_FLAG_PRELIGHT; 1832 } 1833 1834 if (synth_state & FOCUSED) { 1835 flags |= GTK_STATE_FLAG_FOCUSED; 1836 } 1837 1838 fp_gtk_style_context_set_state (context, flags); 1839 1840 if (widget_type == COMBO_BOX_TEXT_FIELD) { 1841 width += height / 2; 1842 } 1843 fp_gtk_render_frame(context, cr, x, y, width, height); 1844 1845 fp_gtk_style_context_restore (context); 1846 1847 /* 1848 * Reset the text direction to the default value so that we don't 1849 * accidentally affect other operations and widgets. 1850 */ 1851 gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR); 1852 } 1853 1854 static void gtk3_paint_slider(WidgetType widget_type, GtkStateType state_type, 1855 GtkShadowType shadow_type, const gchar *detail, 1856 gint x, gint y, gint width, gint height, GtkOrientation orientation, 1857 gboolean has_focus) 1858 { 1859 gtk3_widget = gtk3_get_widget(widget_type); 1860 1861 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1862 1863 fp_gtk_style_context_save (context); 1864 1865 if (detail) { 1866 transform_detail_string(detail, context); 1867 } 1868 1869 GtkStateFlags flags = get_gtk_flags(state_type); 1870 1871 if (state_type == GTK_STATE_ACTIVE) { 1872 flags |= GTK_STATE_FLAG_PRELIGHT; 1873 } 1874 1875 if (has_focus) { 1876 flags |= GTK_STATE_FLAG_FOCUSED; 1877 } 1878 1879 fp_gtk_style_context_set_state (context, flags); 1880 1881 (*fp_gtk_render_slider)(context, cr, x, y, width, height, orientation); 1882 1883 fp_gtk_style_context_restore (context); 1884 } 1885 1886 static void gtk3_paint_background(WidgetType widget_type, 1887 GtkStateType state_type, gint x, gint y, gint width, gint height) { 1888 gtk3_widget = gtk3_get_widget(widget_type); 1889 1890 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1891 fp_gtk_style_context_save (context); 1892 1893 GtkStateFlags flags = get_gtk_flags(state_type); 1894 1895 fp_gtk_style_context_set_state (context, flags); 1896 1897 fp_gtk_render_background (context, cr, x, y, width, height); 1898 1899 fp_gtk_style_context_restore (context); 1900 } 1901 1902 static GdkPixbuf *gtk3_get_stock_icon(gint widget_type, const gchar *stock_id, 1903 GtkIconSize size, GtkTextDirection direction, const char *detail) 1904 { 1905 int sz; 1906 1907 switch(size) { 1908 case GTK_ICON_SIZE_MENU: 1909 sz = 16; 1910 break; 1911 case GTK_ICON_SIZE_SMALL_TOOLBAR: 1912 sz = 18; 1913 break; 1914 case GTK_ICON_SIZE_LARGE_TOOLBAR: 1915 sz = 24; 1916 break; 1917 case GTK_ICON_SIZE_BUTTON: 1918 sz = 20; 1919 break; 1920 case GTK_ICON_SIZE_DND: 1921 sz = 32; 1922 break; 1923 case GTK_ICON_SIZE_DIALOG: 1924 sz = 48; 1925 break; 1926 default: 1927 sz = 0; 1928 break; 1929 } 1930 1931 init_containers(); 1932 gtk3_widget = gtk3_get_widget((widget_type < 0) ? IMAGE : widget_type); 1933 (*fp_gtk_widget_set_direction)(gtk3_widget, direction); 1934 GtkIconTheme *icon_theme = fp_gtk_icon_theme_get_default(); 1935 GdkPixbuf *result = fp_gtk_icon_theme_load_icon(icon_theme, stock_id, sz, 1936 GTK_ICON_LOOKUP_USE_BUILTIN, NULL); 1937 return result; 1938 } 1939 1940 static jboolean gtk3_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf, 1941 jmethodID icon_upcall_method, jobject this) { 1942 if (!pixbuf) { 1943 return JNI_FALSE; 1944 } 1945 guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); 1946 if (pixbuf_data) { 1947 int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); 1948 int width = (*fp_gdk_pixbuf_get_width)(pixbuf); 1949 int height = (*fp_gdk_pixbuf_get_height)(pixbuf); 1950 int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); 1951 int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); 1952 gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); 1953 1954 jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); 1955 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); 1956 1957 (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), 1958 (jbyte *)pixbuf_data); 1959 (*fp_g_object_unref)(pixbuf); 1960 1961 /* Call the callback method to create the image on the Java side. */ 1962 (*env)->CallVoidMethod(env, this, icon_upcall_method, data, 1963 width, height, row_stride, bps, channels, alpha); 1964 return JNI_TRUE; 1965 } 1966 return JNI_FALSE; 1967 } 1968 1969 static jboolean gtk3_get_file_icon_data(JNIEnv *env, const char *filename, 1970 GError **error, jmethodID icon_upcall_method, jobject this) { 1971 GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error); 1972 return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); 1973 } 1974 1975 static jboolean gtk3_get_icon_data(JNIEnv *env, gint widget_type, 1976 const gchar *stock_id, GtkIconSize size, 1977 GtkTextDirection direction, const char *detail, 1978 jmethodID icon_upcall_method, jobject this) { 1979 GdkPixbuf* pixbuf = gtk3_get_stock_icon(widget_type, stock_id, size, 1980 direction, detail); 1981 return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); 1982 } 1983 1984 /*************************************************/ 1985 static gint gtk3_get_xthickness(JNIEnv *env, WidgetType widget_type) 1986 { 1987 init_containers(); 1988 1989 gtk3_widget = gtk3_get_widget(widget_type); 1990 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 1991 if (context) { 1992 GtkBorder padding; 1993 fp_gtk_style_context_get_padding(context, 0, &padding); 1994 return padding.left + 1; 1995 } 1996 return 0; 1997 } 1998 1999 static gint gtk3_get_ythickness(JNIEnv *env, WidgetType widget_type) 2000 { 2001 init_containers(); 2002 2003 gtk3_widget = gtk3_get_widget(widget_type); 2004 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 2005 if (context) { 2006 GtkBorder padding; 2007 fp_gtk_style_context_get_padding(context, 0, &padding); 2008 return padding.top + 1; 2009 } 2010 return 0; 2011 } 2012 2013 /*************************************************/ 2014 static guint8 recode_color(gdouble channel) 2015 { 2016 guint16 result = (guint16)(channel * 65535); 2017 return (guint8)( result >> 8); 2018 } 2019 2020 static GtkStateFlags gtk3_get_state_flags(GtkStateType state_type) { 2021 switch (state_type) 2022 { 2023 case GTK_STATE_NORMAL: 2024 return GTK_STATE_FLAG_NORMAL; 2025 case GTK_STATE_ACTIVE: 2026 return GTK_STATE_FLAG_ACTIVE; 2027 case GTK_STATE_PRELIGHT: 2028 return GTK_STATE_FLAG_PRELIGHT; 2029 case GTK_STATE_SELECTED: 2030 return GTK_STATE_FLAG_SELECTED; 2031 case GTK_STATE_INSENSITIVE: 2032 return GTK_STATE_FLAG_INSENSITIVE; 2033 case GTK_STATE_INCONSISTENT: 2034 return GTK_STATE_FLAG_INCONSISTENT; 2035 case GTK_STATE_FOCUSED: 2036 return GTK_STATE_FLAG_FOCUSED; 2037 } 2038 return 0; 2039 } 2040 2041 2042 static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b) { 2043 gdouble min; 2044 gdouble max; 2045 gdouble red; 2046 gdouble green; 2047 gdouble blue; 2048 gdouble h, l, s; 2049 gdouble delta; 2050 2051 red = *r; 2052 green = *g; 2053 blue = *b; 2054 2055 if (red > green) 2056 { 2057 if (red > blue) 2058 max = red; 2059 else 2060 max = blue; 2061 2062 if (green < blue) 2063 min = green; 2064 else 2065 min = blue; 2066 } 2067 else 2068 { 2069 if (green > blue) 2070 max = green; 2071 else 2072 max = blue; 2073 2074 if (red < blue) 2075 min = red; 2076 else 2077 min = blue; 2078 } 2079 2080 l = (max + min) / 2; 2081 s = 0; 2082 h = 0; 2083 2084 if (max != min) 2085 { 2086 if (l <= 0.5) 2087 s = (max - min) / (max + min); 2088 else 2089 s = (max - min) / (2 - max - min); 2090 2091 delta = max -min; 2092 if (red == max) 2093 h = (green - blue) / delta; 2094 else if (green == max) 2095 h = 2 + (blue - red) / delta; 2096 else if (blue == max) 2097 h = 4 + (red - green) / delta; 2098 2099 h *= 60; 2100 if (h < 0.0) 2101 h += 360; 2102 } 2103 2104 *r = h; 2105 *g = l; 2106 *b = s; 2107 } 2108 2109 static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s) 2110 { 2111 gdouble hue; 2112 gdouble lightness; 2113 gdouble saturation; 2114 gdouble m1, m2; 2115 gdouble r, g, b; 2116 2117 lightness = *l; 2118 saturation = *s; 2119 2120 if (lightness <= 0.5) 2121 m2 = lightness * (1 + saturation); 2122 else 2123 m2 = lightness + saturation - lightness * saturation; 2124 m1 = 2 * lightness - m2; 2125 2126 if (saturation == 0) 2127 { 2128 *h = lightness; 2129 *l = lightness; 2130 *s = lightness; 2131 } 2132 else 2133 { 2134 hue = *h + 120; 2135 while (hue > 360) 2136 hue -= 360; 2137 while (hue < 0) 2138 hue += 360; 2139 2140 if (hue < 60) 2141 r = m1 + (m2 - m1) * hue / 60; 2142 else if (hue < 180) 2143 r = m2; 2144 else if (hue < 240) 2145 r = m1 + (m2 - m1) * (240 - hue) / 60; 2146 else 2147 r = m1; 2148 2149 hue = *h; 2150 while (hue > 360) 2151 hue -= 360; 2152 while (hue < 0) 2153 hue += 360; 2154 2155 if (hue < 60) 2156 g = m1 + (m2 - m1) * hue / 60; 2157 else if (hue < 180) 2158 g = m2; 2159 else if (hue < 240) 2160 g = m1 + (m2 - m1) * (240 - hue) / 60; 2161 else 2162 g = m1; 2163 2164 hue = *h - 120; 2165 while (hue > 360) 2166 hue -= 360; 2167 while (hue < 0) 2168 hue += 360; 2169 2170 if (hue < 60) 2171 b = m1 + (m2 - m1) * hue / 60; 2172 else if (hue < 180) 2173 b = m2; 2174 else if (hue < 240) 2175 b = m1 + (m2 - m1) * (240 - hue) / 60; 2176 else 2177 b = m1; 2178 2179 *h = r; 2180 *l = g; 2181 *s = b; 2182 } 2183 } 2184 2185 2186 2187 static void gtk3_style_shade (const GdkRGBA *a, GdkRGBA *b, gdouble k) { 2188 gdouble red = a->red; 2189 gdouble green = a->green; 2190 gdouble blue = a->blue; 2191 2192 rgb_to_hls (&red, &green, &blue); 2193 2194 green *= k; 2195 if (green > 1.0) 2196 green = 1.0; 2197 else if (green < 0.0) 2198 green = 0.0; 2199 2200 blue *= k; 2201 if (blue > 1.0) 2202 blue = 1.0; 2203 else if (blue < 0.0) 2204 blue = 0.0; 2205 2206 hls_to_rgb (&red, &green, &blue); 2207 2208 b->red = red; 2209 b->green = green; 2210 b->blue = blue; 2211 } 2212 2213 static GdkRGBA gtk3_get_color_for_flags(GtkStyleContext* context, 2214 GtkStateFlags flags, ColorType color_type) { 2215 GdkRGBA c, color; 2216 color.alpha = 1; 2217 2218 switch (color_type) 2219 { 2220 case FOREGROUND: 2221 case TEXT_FOREGROUND: 2222 fp_gtk_style_context_get_color(context, flags, &color); 2223 break; 2224 case BACKGROUND: 2225 case TEXT_BACKGROUND: 2226 fp_gtk_style_context_get_background_color(context, flags, &color); 2227 break; 2228 case LIGHT: 2229 c = gtk3_get_color_for_flags(context, flags, BACKGROUND); 2230 gtk3_style_shade(&c, &color, LIGHTNESS_MULT); 2231 break; 2232 case DARK: 2233 c = gtk3_get_color_for_flags(context, flags, BACKGROUND); 2234 gtk3_style_shade (&c, &color, DARKNESS_MULT); 2235 break; 2236 case MID: 2237 { 2238 GdkRGBA c1 = gtk3_get_color_for_flags(context, flags, LIGHT); 2239 GdkRGBA c2 = gtk3_get_color_for_flags(context, flags, DARK); 2240 color.red = (c1.red + c2.red) / 2; 2241 color.green = (c1.green + c2.green) / 2; 2242 color.blue = (c1.blue + c2.blue) / 2; 2243 } 2244 break; 2245 case FOCUS: 2246 case BLACK: 2247 color.red = 0; 2248 color.green = 0; 2249 color.blue = 0; 2250 break; 2251 case WHITE: 2252 color.red = 1; 2253 color.green = 1; 2254 color.blue = 1; 2255 break; 2256 } 2257 return color; 2258 } 2259 2260 static gint gtk3_get_color_for_state(JNIEnv *env, WidgetType widget_type, 2261 GtkStateType state_type, ColorType color_type) 2262 { 2263 2264 gint result = 0; 2265 2266 GtkStateFlags flags = gtk3_get_state_flags(state_type); 2267 2268 init_containers(); 2269 2270 gtk3_widget = gtk3_get_widget(widget_type); 2271 2272 GtkStyleContext* context = fp_gtk_widget_get_style_context(gtk3_widget); 2273 2274 if (widget_type == TOOL_TIP) { 2275 fp_gtk_style_context_add_class(context, "tooltip"); 2276 } 2277 if (widget_type == CHECK_BOX_MENU_ITEM 2278 || widget_type == RADIO_BUTTON_MENU_ITEM) { 2279 flags &= GTK_STATE_FLAG_NORMAL | GTK_STATE_FLAG_SELECTED 2280 | GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_FOCUSED; 2281 } 2282 2283 GdkRGBA color = gtk3_get_color_for_flags(context, flags, color_type); 2284 2285 if (recode_color(color.alpha) == 0) { 2286 color = gtk3_get_color_for_flags( 2287 fp_gtk_widget_get_style_context(gtk3_get_widget(INTERNAL_FRAME)), 2288 0, BACKGROUND); 2289 } 2290 2291 result = recode_color(color.alpha) << 24 | recode_color(color.red) << 16 | 2292 recode_color(color.green) << 8 | recode_color(color.blue); 2293 2294 return result; 2295 } 2296 2297 /*************************************************/ 2298 static jobject create_Boolean(JNIEnv *env, jboolean boolean_value); 2299 static jobject create_Integer(JNIEnv *env, jint int_value); 2300 static jobject create_Long(JNIEnv *env, jlong long_value); 2301 static jobject create_Float(JNIEnv *env, jfloat float_value); 2302 static jobject create_Double(JNIEnv *env, jdouble double_value); 2303 static jobject create_Character(JNIEnv *env, jchar char_value); 2304 static jobject create_Insets(JNIEnv *env, GtkBorder *border); 2305 2306 static jobject gtk3_get_class_value(JNIEnv *env, WidgetType widget_type, 2307 const char* key) 2308 { 2309 init_containers(); 2310 2311 gtk3_widget = gtk3_get_widget(widget_type); 2312 2313 GValue value = { 0, { { 0 } } }; 2314 2315 GParamSpec* param = (*fp_gtk_widget_class_find_style_property)( 2316 ((GTypeInstance*)gtk3_widget)->g_class, key); 2317 if ( param ) 2318 { 2319 (*fp_g_value_init)( &value, param->value_type ); 2320 (*fp_gtk_widget_style_get_property)(gtk3_widget, key, &value); 2321 2322 if ((*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN )) 2323 { 2324 gboolean val = (*fp_g_value_get_boolean)(&value); 2325 return create_Boolean(env, (jboolean)val); 2326 } 2327 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR )) 2328 { 2329 gchar val = (*fp_g_value_get_char)(&value); 2330 return create_Character(env, (jchar)val); 2331 } 2332 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR )) 2333 { 2334 guchar val = (*fp_g_value_get_uchar)(&value); 2335 return create_Character(env, (jchar)val); 2336 } 2337 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT )) 2338 { 2339 gint val = (*fp_g_value_get_int)(&value); 2340 return create_Integer(env, (jint)val); 2341 } 2342 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT )) 2343 { 2344 guint val = (*fp_g_value_get_uint)(&value); 2345 return create_Integer(env, (jint)val); 2346 } 2347 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_LONG )) 2348 { 2349 glong val = (*fp_g_value_get_long)(&value); 2350 return create_Long(env, (jlong)val); 2351 } 2352 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG )) 2353 { 2354 gulong val = (*fp_g_value_get_ulong)(&value); 2355 return create_Long(env, (jlong)val); 2356 } 2357 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 )) 2358 { 2359 gint64 val = (*fp_g_value_get_int64)(&value); 2360 return create_Long(env, (jlong)val); 2361 } 2362 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 )) 2363 { 2364 guint64 val = (*fp_g_value_get_uint64)(&value); 2365 return create_Long(env, (jlong)val); 2366 } 2367 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT )) 2368 { 2369 gfloat val = (*fp_g_value_get_float)(&value); 2370 return create_Float(env, (jfloat)val); 2371 } 2372 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE )) 2373 { 2374 gdouble val = (*fp_g_value_get_double)(&value); 2375 return create_Double(env, (jdouble)val); 2376 } 2377 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM )) 2378 { 2379 gint val = (*fp_g_value_get_enum)(&value); 2380 return create_Integer(env, (jint)val); 2381 } 2382 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS )) 2383 { 2384 guint val = (*fp_g_value_get_flags)(&value); 2385 return create_Integer(env, (jint)val); 2386 } 2387 else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_STRING )) 2388 { 2389 const gchar* val = (*fp_g_value_get_string)(&value); 2390 2391 /* We suppose that all values come in C locale and 2392 * utf-8 representation of a string is the same as 2393 * the string itself. If this isn't so we should 2394 * use g_convert. 2395 */ 2396 return (*env)->NewStringUTF(env, val); 2397 } 2398 else if ((*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER )) 2399 { 2400 GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value); 2401 return border ? create_Insets(env, border) : NULL; 2402 } 2403 2404 /* TODO: Other types are not supported yet.*/ 2405 /* else if((*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM )) 2406 { 2407 GParamSpec* val = (*fp_g_value_get_param)(&value); 2408 printf( "Param: %p\n", val ); 2409 } 2410 else if((*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED )) 2411 { 2412 gpointer* val = (*fp_g_value_get_boxed)(&value); 2413 printf( "Boxed: %p\n", val ); 2414 } 2415 else if((*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER )) 2416 { 2417 gpointer* val = (*fp_g_value_get_pointer)(&value); 2418 printf( "Pointer: %p\n", val ); 2419 } 2420 else if((*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT )) 2421 { 2422 GObject* val = (GObject*)(*fp_g_value_get_object)(&value); 2423 printf( "Object: %p\n", val ); 2424 }*/ 2425 } 2426 2427 return NULL; 2428 } 2429 2430 static void gtk3_set_range_value(WidgetType widget_type, jdouble value, 2431 jdouble min, jdouble max, jdouble visible) 2432 { 2433 GtkAdjustment *adj; 2434 2435 gtk3_widget = gtk3_get_widget(widget_type); 2436 2437 adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk3_widget); 2438 2439 fp_gtk_adjustment_set_value(adj, value); 2440 fp_gtk_adjustment_set_lower(adj, min); 2441 fp_gtk_adjustment_set_upper(adj, max); 2442 fp_gtk_adjustment_set_page_size(adj, visible); 2443 } 2444 2445 /*************************************************/ 2446 static jobject create_Object(JNIEnv *env, jmethodID *cid, 2447 const char* class_name, 2448 const char* signature, 2449 jvalue* value) 2450 { 2451 jclass class; 2452 jobject result; 2453 2454 class = (*env)->FindClass(env, class_name); 2455 if (class == NULL) 2456 return NULL; /* can't find/load the class, exception thrown */ 2457 2458 if (*cid == NULL) 2459 { 2460 *cid = (*env)->GetMethodID(env, class, "<init>", signature); 2461 if (*cid == NULL) 2462 { 2463 (*env)->DeleteLocalRef(env, class); 2464 return NULL; /* can't find/get the method, exception thrown */ 2465 } 2466 } 2467 2468 result = (*env)->NewObjectA(env, class, *cid, value); 2469 2470 (*env)->DeleteLocalRef(env, class); 2471 return result; 2472 } 2473 2474 jobject create_Boolean(JNIEnv *env, jboolean boolean_value) 2475 { 2476 static jmethodID cid = NULL; 2477 jvalue value; 2478 2479 value.z = boolean_value; 2480 2481 return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value); 2482 } 2483 2484 jobject create_Integer(JNIEnv *env, jint int_value) 2485 { 2486 static jmethodID cid = NULL; 2487 jvalue value; 2488 2489 value.i = int_value; 2490 2491 return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value); 2492 } 2493 2494 jobject create_Long(JNIEnv *env, jlong long_value) 2495 { 2496 static jmethodID cid = NULL; 2497 jvalue value; 2498 2499 value.j = long_value; 2500 2501 return create_Object(env, &cid, "java/lang/Long", "(J)V", &value); 2502 } 2503 2504 jobject create_Float(JNIEnv *env, jfloat float_value) 2505 { 2506 static jmethodID cid = NULL; 2507 jvalue value; 2508 2509 value.f = float_value; 2510 2511 return create_Object(env, &cid, "java/lang/Float", "(F)V", &value); 2512 } 2513 2514 jobject create_Double(JNIEnv *env, jdouble double_value) 2515 { 2516 static jmethodID cid = NULL; 2517 jvalue value; 2518 2519 value.d = double_value; 2520 2521 return create_Object(env, &cid, "java/lang/Double", "(D)V", &value); 2522 } 2523 2524 jobject create_Character(JNIEnv *env, jchar char_value) 2525 { 2526 static jmethodID cid = NULL; 2527 jvalue value; 2528 2529 value.c = char_value; 2530 2531 return create_Object(env, &cid, "java/lang/Character", "(C)V", &value); 2532 } 2533 2534 2535 jobject create_Insets(JNIEnv *env, GtkBorder *border) 2536 { 2537 static jmethodID cid = NULL; 2538 jvalue values[4]; 2539 2540 values[0].i = border->top; 2541 values[1].i = border->left; 2542 values[2].i = border->bottom; 2543 values[3].i = border->right; 2544 2545 return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values); 2546 } 2547 2548 /*********************************************/ 2549 static jstring gtk3_get_pango_font_name(JNIEnv *env, WidgetType widget_type) 2550 { 2551 init_containers(); 2552 2553 gtk3_widget = gtk3_get_widget(widget_type); 2554 jstring result = NULL; 2555 GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget); 2556 if (context) 2557 { 2558 PangoFontDescription* fd = fp_gtk_style_context_get_font(context, 0); 2559 gchar* val = (*fp_pango_font_description_to_string)(fd); 2560 result = (*env)->NewStringUTF(env, val); 2561 (*fp_g_free)( val ); 2562 } 2563 2564 return result; 2565 } 2566 2567 /***********************************************/ 2568 static jobject get_string_property(JNIEnv *env, GtkSettings* settings, 2569 const gchar* key) { 2570 jobject result = NULL; 2571 gchar* strval = NULL; 2572 2573 (*fp_g_object_get)(settings, key, &strval, NULL); 2574 result = (*env)->NewStringUTF(env, strval); 2575 (*fp_g_free)(strval); 2576 2577 return result; 2578 } 2579 2580 static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, 2581 const gchar* key) { 2582 gint intval = 0; 2583 (*fp_g_object_get)(settings, key, &intval, NULL); 2584 return create_Integer(env, intval); 2585 } 2586 2587 static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, 2588 const gchar* key) { 2589 gint intval = 0; 2590 (*fp_g_object_get)(settings, key, &intval, NULL); 2591 return create_Boolean(env, intval); 2592 } 2593 2594 static jobject gtk3_get_setting(JNIEnv *env, Setting property) 2595 { 2596 GtkSettings* settings = (*fp_gtk_settings_get_default)(); 2597 2598 switch (property) 2599 { 2600 case GTK_FONT_NAME: 2601 return get_string_property(env, settings, "gtk-font-name"); 2602 case GTK_ICON_SIZES: 2603 return get_string_property(env, settings, "gtk-icon-sizes"); 2604 case GTK_CURSOR_BLINK: 2605 return get_boolean_property(env, settings, "gtk-cursor-blink"); 2606 case GTK_CURSOR_BLINK_TIME: 2607 return get_integer_property(env, settings, "gtk-cursor-blink-time"); 2608 } 2609 2610 return NULL; 2611 } 2612 2613 static void transform_detail_string (const gchar *detail, 2614 GtkStyleContext *context) { 2615 if (!detail) 2616 return; 2617 2618 if (strcmp (detail, "arrow") == 0) 2619 fp_gtk_style_context_add_class (context, "arrow"); 2620 else if (strcmp (detail, "button") == 0) 2621 fp_gtk_style_context_add_class (context, "button"); 2622 else if (strcmp (detail, "buttondefault") == 0) 2623 { 2624 fp_gtk_style_context_add_class (context, "button"); 2625 fp_gtk_style_context_add_class (context, "default"); 2626 } 2627 else if (strcmp (detail, "calendar") == 0) 2628 fp_gtk_style_context_add_class (context, "calendar"); 2629 else if (strcmp (detail, "cellcheck") == 0) 2630 { 2631 fp_gtk_style_context_add_class (context, "cell"); 2632 fp_gtk_style_context_add_class (context, "check"); 2633 } 2634 else if (strcmp (detail, "cellradio") == 0) 2635 { 2636 fp_gtk_style_context_add_class (context, "cell"); 2637 fp_gtk_style_context_add_class (context, "radio"); 2638 } 2639 else if (strcmp (detail, "checkbutton") == 0) 2640 fp_gtk_style_context_add_class (context, "check"); 2641 else if (strcmp (detail, "check") == 0) 2642 { 2643 fp_gtk_style_context_add_class (context, "check"); 2644 fp_gtk_style_context_add_class (context, "menu"); 2645 } 2646 else if (strcmp (detail, "radiobutton") == 0) 2647 { 2648 fp_gtk_style_context_add_class (context, "radio"); 2649 } 2650 else if (strcmp (detail, "option") == 0) 2651 { 2652 fp_gtk_style_context_add_class (context, "radio"); 2653 fp_gtk_style_context_add_class (context, "menu"); 2654 } 2655 else if (strcmp (detail, "entry") == 0 || 2656 strcmp (detail, "entry_bg") == 0) 2657 fp_gtk_style_context_add_class (context, "entry"); 2658 else if (strcmp (detail, "expander") == 0) 2659 fp_gtk_style_context_add_class (context, "expander"); 2660 else if (strcmp (detail, "tooltip") == 0) 2661 fp_gtk_style_context_add_class (context, "tooltip"); 2662 else if (strcmp (detail, "frame") == 0) 2663 fp_gtk_style_context_add_class (context, "frame"); 2664 else if (strcmp (detail, "scrolled_window") == 0) 2665 fp_gtk_style_context_add_class (context, "scrolled-window"); 2666 else if (strcmp (detail, "viewport") == 0 || 2667 strcmp (detail, "viewportbin") == 0) 2668 fp_gtk_style_context_add_class (context, "viewport"); 2669 else if (strncmp (detail, "trough", 6) == 0) 2670 fp_gtk_style_context_add_class (context, "trough"); 2671 else if (strcmp (detail, "spinbutton") == 0) 2672 fp_gtk_style_context_add_class (context, "spinbutton"); 2673 else if (strcmp (detail, "spinbutton_up") == 0) 2674 { 2675 fp_gtk_style_context_add_class (context, "spinbutton"); 2676 fp_gtk_style_context_add_class (context, "button"); 2677 fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM); 2678 } 2679 else if (strcmp (detail, "spinbutton_down") == 0) 2680 { 2681 fp_gtk_style_context_add_class (context, "spinbutton"); 2682 fp_gtk_style_context_add_class (context, "button"); 2683 fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP); 2684 } 2685 else if ((detail[0] == 'h' || detail[0] == 'v') && 2686 strncmp (&detail[1], "scrollbar_", 9) == 0) 2687 { 2688 fp_gtk_style_context_add_class (context, "button"); 2689 fp_gtk_style_context_add_class (context, "scrollbar"); 2690 } 2691 else if (strcmp (detail, "slider") == 0) 2692 { 2693 fp_gtk_style_context_add_class (context, "slider"); 2694 fp_gtk_style_context_add_class (context, "scrollbar"); 2695 } 2696 else if (strcmp (detail, "vscale") == 0 || 2697 strcmp (detail, "hscale") == 0) 2698 { 2699 fp_gtk_style_context_add_class (context, "slider"); 2700 fp_gtk_style_context_add_class (context, "scale"); 2701 } 2702 else if (strcmp (detail, "menuitem") == 0) 2703 { 2704 fp_gtk_style_context_add_class (context, "menuitem"); 2705 fp_gtk_style_context_add_class (context, "menu"); 2706 } 2707 else if (strcmp (detail, "menu") == 0) 2708 { 2709 fp_gtk_style_context_add_class (context, "popup"); 2710 fp_gtk_style_context_add_class (context, "menu"); 2711 } 2712 else if (strcmp (detail, "accellabel") == 0) 2713 fp_gtk_style_context_add_class (context, "accelerator"); 2714 else if (strcmp (detail, "menubar") == 0) 2715 fp_gtk_style_context_add_class (context, "menubar"); 2716 else if (strcmp (detail, "base") == 0) 2717 fp_gtk_style_context_add_class (context, "background"); 2718 else if (strcmp (detail, "bar") == 0 || 2719 strcmp (detail, "progressbar") == 0) 2720 fp_gtk_style_context_add_class (context, "progressbar"); 2721 else if (strcmp (detail, "toolbar") == 0) 2722 fp_gtk_style_context_add_class (context, "toolbar"); 2723 else if (strcmp (detail, "handlebox_bin") == 0) 2724 fp_gtk_style_context_add_class (context, "dock"); 2725 else if (strcmp (detail, "notebook") == 0) 2726 fp_gtk_style_context_add_class (context, "notebook"); 2727 else if (strcmp (detail, "tab") == 0) 2728 { 2729 fp_gtk_style_context_add_class (context, "notebook"); 2730 fp_gtk_style_context_add_region (context, "tab", 0); 2731 } else if (strcmp (detail, "paned") == 0) { 2732 fp_gtk_style_context_add_class (context, "pane-separator"); 2733 } 2734 else if (fp_g_str_has_prefix (detail, "cell")) 2735 { 2736 GtkRegionFlags row, col; 2737 gboolean ruled = FALSE; 2738 gchar** tokens; 2739 guint i; 2740 2741 tokens = fp_g_strsplit (detail, "_", -1); 2742 row = col = 0; 2743 i = 0; 2744 2745 while (tokens[i]) 2746 { 2747 if (strcmp (tokens[i], "even") == 0) 2748 row |= GTK_REGION_EVEN; 2749 else if (strcmp (tokens[i], "odd") == 0) 2750 row |= GTK_REGION_ODD; 2751 else if (strcmp (tokens[i], "start") == 0) 2752 col |= GTK_REGION_FIRST; 2753 else if (strcmp (tokens[i], "end") == 0) 2754 col |= GTK_REGION_LAST; 2755 else if (strcmp (tokens[i], "ruled") == 0) 2756 ruled = TRUE; 2757 else if (strcmp (tokens[i], "sorted") == 0) 2758 col |= GTK_REGION_SORTED; 2759 2760 i++; 2761 } 2762 2763 if (!ruled) 2764 row &= ~(GTK_REGION_EVEN | GTK_REGION_ODD); 2765 2766 fp_gtk_style_context_add_class (context, "cell"); 2767 fp_gtk_style_context_add_region (context, "row", row); 2768 fp_gtk_style_context_add_region (context, "column", col); 2769 2770 fp_g_strfreev (tokens); 2771 } 2772 } 2773 2774 static gboolean gtk3_get_drawable_data(JNIEnv *env, jintArray pixelArray, 2775 int x, jint y, jint width, jint height, jint jwidth, int dx, int dy, 2776 jint scale) { 2777 GdkPixbuf *pixbuf; 2778 jint *ary; 2779 2780 GdkWindow *root = (*fp_gdk_get_default_root_window)(); 2781 pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(root, x, y, width, height); 2782 if (pixbuf && scale != 1) { 2783 GdkPixbuf *scaledPixbuf; 2784 x /= scale; 2785 y /= scale; 2786 width /= scale; 2787 height /= scale; 2788 dx /= scale; 2789 dy /= scale; 2790 scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height, 2791 GDK_INTERP_BILINEAR); 2792 (*fp_g_object_unref)(pixbuf); 2793 pixbuf = scaledPixbuf; 2794 } 2795 2796 if (pixbuf) { 2797 int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); 2798 int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); 2799 if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width 2800 && (*fp_gdk_pixbuf_get_height)(pixbuf) == height 2801 && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8 2802 && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB 2803 && nchan >= 3 2804 ) { 2805 guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf); 2806 ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); 2807 if (ary) { 2808 jint _x, _y; 2809 int index; 2810 for (_y = 0; _y < height; _y++) { 2811 for (_x = 0; _x < width; _x++) { 2812 p = pix + _y * stride + _x * nchan; 2813 2814 index = (_y + dy) * jwidth + (_x + dx); 2815 ary[index] = 0xff000000 2816 | (p[0] << 16) 2817 | (p[1] << 8) 2818 | (p[2]); 2819 2820 } 2821 } 2822 (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); 2823 } 2824 } 2825 (*fp_g_object_unref)(pixbuf); 2826 } 2827 return JNI_FALSE; 2828 } 2829 2830 static GdkWindow* gtk3_get_window(void *widget) { 2831 return fp_gtk_widget_get_window((GtkWidget*)widget); 2832 } 2833 2834 static void gtk3_init(GtkApi* gtk) { 2835 gtk->version = GTK_3; 2836 2837 gtk->show_uri_load = >k3_show_uri_load; 2838 gtk->unload = >k3_unload; 2839 gtk->flush_event_loop = &flush_gtk_event_loop; 2840 gtk->gtk_check_version = fp_gtk_check_version; 2841 gtk->get_setting = >k3_get_setting; 2842 2843 gtk->paint_arrow = >k3_paint_arrow; 2844 gtk->paint_box = >k3_paint_box; 2845 gtk->paint_box_gap = >k3_paint_box_gap; 2846 gtk->paint_expander = >k3_paint_expander; 2847 gtk->paint_extension = >k3_paint_extension; 2848 gtk->paint_flat_box = >k3_paint_flat_box; 2849 gtk->paint_focus = >k3_paint_focus; 2850 gtk->paint_handle = >k3_paint_handle; 2851 gtk->paint_hline = >k3_paint_hline; 2852 gtk->paint_vline = >k3_paint_vline; 2853 gtk->paint_option = >k3_paint_option; 2854 gtk->paint_shadow = >k3_paint_shadow; 2855 gtk->paint_slider = >k3_paint_slider; 2856 gtk->paint_background = >k3_paint_background; 2857 gtk->paint_check = >k3_paint_check; 2858 gtk->set_range_value = >k3_set_range_value; 2859 2860 gtk->init_painting = >k3_init_painting; 2861 gtk->copy_image = >k3_copy_image; 2862 2863 gtk->get_xthickness = >k3_get_xthickness; 2864 gtk->get_ythickness = >k3_get_ythickness; 2865 gtk->get_color_for_state = >k3_get_color_for_state; 2866 gtk->get_class_value = >k3_get_class_value; 2867 2868 gtk->get_pango_font_name = >k3_get_pango_font_name; 2869 gtk->get_icon_data = >k3_get_icon_data; 2870 gtk->get_file_icon_data = >k3_get_file_icon_data; 2871 gtk->gdk_threads_enter = fp_gdk_threads_enter; 2872 gtk->gdk_threads_leave = fp_gdk_threads_leave; 2873 gtk->gtk_show_uri = fp_gtk_show_uri; 2874 gtk->get_drawable_data = >k3_get_drawable_data; 2875 gtk->g_free = fp_g_free; 2876 2877 gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename; 2878 gtk->gtk_widget_hide = fp_gtk_widget_hide; 2879 gtk->gtk_main_quit = fp_gtk_main_quit; 2880 gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new; 2881 gtk->gtk_file_chooser_set_current_folder = 2882 fp_gtk_file_chooser_set_current_folder; 2883 gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename; 2884 gtk->gtk_file_chooser_set_current_name = 2885 fp_gtk_file_chooser_set_current_name; 2886 gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom; 2887 gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter; 2888 gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type; 2889 gtk->gtk_file_filter_new = fp_gtk_file_filter_new; 2890 gtk->gtk_file_chooser_set_do_overwrite_confirmation = 2891 fp_gtk_file_chooser_set_do_overwrite_confirmation; 2892 gtk->gtk_file_chooser_set_select_multiple = 2893 fp_gtk_file_chooser_set_select_multiple; 2894 gtk->gtk_file_chooser_get_current_folder = 2895 fp_gtk_file_chooser_get_current_folder; 2896 gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames; 2897 gtk->gtk_g_slist_length = fp_gtk_g_slist_length; 2898 gtk->g_signal_connect_data = fp_g_signal_connect_data; 2899 gtk->gtk_widget_show = fp_gtk_widget_show; 2900 gtk->gtk_main = fp_gtk_main; 2901 gtk->gtk_main_level = fp_gtk_main_level; 2902 gtk->g_path_get_dirname = fp_g_path_get_dirname; 2903 gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid; 2904 gtk->gtk_widget_destroy = fp_gtk_widget_destroy; 2905 gtk->gtk_window_present = fp_gtk_window_present; 2906 gtk->gtk_window_move = fp_gtk_window_move; 2907 gtk->gtk_window_resize = fp_gtk_window_resize; 2908 gtk->get_window = >k3_get_window; 2909 2910 gtk->g_object_unref = fp_g_object_unref; 2911 gtk->g_list_append = fp_g_list_append; 2912 gtk->g_list_free = fp_g_list_free; 2913 gtk->g_list_free_full = fp_g_list_free_full; 2914 }