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