1 /* 2 * Copyright (c) 2005, 2017, 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 <stdio.h> 30 #include <string.h> 31 #include "gtk2_interface.h" 32 #include "java_awt_Transparency.h" 33 #include "jvm_md.h" 34 #include "sizecalc.h" 35 #include <jni_util.h> 36 #include "awt.h" 37 38 #define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)()) 39 40 #define G_TYPE_FUNDAMENTAL_SHIFT (2) 41 #define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT)) 42 43 #define CONV_BUFFER_SIZE 128 44 45 #define NO_SYMBOL_EXCEPTION 1 46 47 static void *gtk2_libhandle = NULL; 48 static void *gthread_libhandle = NULL; 49 50 static jmp_buf j; 51 52 /* Widgets */ 53 static GtkWidget *gtk2_widget = NULL; 54 static GtkWidget *gtk2_window = NULL; 55 static GtkFixed *gtk2_fixed = NULL; 56 57 /* Paint system */ 58 static GdkPixmap *gtk2_white_pixmap = NULL; 59 static GdkPixmap *gtk2_black_pixmap = NULL; 60 static GdkPixbuf *gtk2_white_pixbuf = NULL; 61 static GdkPixbuf *gtk2_black_pixbuf = NULL; 62 static int gtk2_pixbuf_width = 0; 63 static int gtk2_pixbuf_height = 0; 64 65 /* Static buffer for conversion from java.lang.String to UTF-8 */ 66 static char convertionBuffer[CONV_BUFFER_SIZE]; 67 68 static gboolean new_combo = TRUE; 69 const char ENV_PREFIX[] = "GTK_MODULES="; 70 71 72 static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE]; 73 74 /************************* 75 * Glib function pointers 76 *************************/ 77 78 static gboolean (*fp_g_main_context_iteration)(GMainContext *context, 79 gboolean may_block); 80 81 static GValue* (*fp_g_value_init)(GValue *value, GType g_type); 82 static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type); 83 static gboolean (*fp_g_value_get_boolean)(const GValue *value); 84 static gchar (*fp_g_value_get_char)(const GValue *value); 85 static guchar (*fp_g_value_get_uchar)(const GValue *value); 86 static gint (*fp_g_value_get_int)(const GValue *value); 87 static guint (*fp_g_value_get_uint)(const GValue *value); 88 static glong (*fp_g_value_get_long)(const GValue *value); 89 static gulong (*fp_g_value_get_ulong)(const GValue *value); 90 static gint64 (*fp_g_value_get_int64)(const GValue *value); 91 static guint64 (*fp_g_value_get_uint64)(const GValue *value); 92 static gfloat (*fp_g_value_get_float)(const GValue *value); 93 static gdouble (*fp_g_value_get_double)(const GValue *value); 94 static const gchar* (*fp_g_value_get_string)(const GValue *value); 95 static gint (*fp_g_value_get_enum)(const GValue *value); 96 static guint (*fp_g_value_get_flags)(const GValue *value); 97 static GParamSpec* (*fp_g_value_get_param)(const GValue *value); 98 static gpointer* (*fp_g_value_get_boxed)(const GValue *value); 99 static gpointer* (*fp_g_value_get_pointer)(const GValue *value); 100 static GObject* (*fp_g_value_get_object)(const GValue *value); 101 static GParamSpec* (*fp_g_param_spec_int)(const gchar *name, 102 const gchar *nick, const gchar *blurb, 103 gint minimum, gint maximum, gint default_value, 104 GParamFlags flags); 105 static void (*fp_g_object_get)(gpointer object, 106 const gchar* fpn, ...); 107 static void (*fp_g_object_set)(gpointer object, 108 const gchar *first_property_name, 109 ...); 110 /************************ 111 * GDK function pointers 112 ************************/ 113 static GdkPixmap *(*fp_gdk_pixmap_new)(GdkDrawable *drawable, 114 gint width, gint height, gint depth); 115 static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*); 116 static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32); 117 static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean, 118 gint, gint, gint, gint); 119 static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace, 120 gboolean has_alpha, int bits_per_sample, int width, int height); 121 static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable, 122 gint* width, gint* height); 123 124 /************************ 125 * Gtk function pointers 126 ************************/ 127 static gboolean (*fp_gtk_init_check)(int* argc, char** argv); 128 129 /* Painting */ 130 static void (*fp_gtk_paint_hline)(GtkStyle* style, GdkWindow* window, 131 GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, 132 const gchar* detail, gint x1, gint x2, gint y); 133 static void (*fp_gtk_paint_vline)(GtkStyle* style, GdkWindow* window, 134 GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, 135 const gchar* detail, gint y1, gint y2, gint x); 136 static void (*fp_gtk_paint_shadow)(GtkStyle* style, GdkWindow* window, 137 GtkStateType state_type, GtkShadowType shadow_type, 138 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 139 gint x, gint y, gint width, gint height); 140 static void (*fp_gtk_paint_arrow)(GtkStyle* style, GdkWindow* window, 141 GtkStateType state_type, GtkShadowType shadow_type, 142 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 143 GtkArrowType arrow_type, gboolean fill, gint x, gint y, 144 gint width, gint height); 145 static void (*fp_gtk_paint_diamond)(GtkStyle* style, GdkWindow* window, 146 GtkStateType state_type, GtkShadowType shadow_type, 147 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 148 gint x, gint y, gint width, gint height); 149 static void (*fp_gtk_paint_box)(GtkStyle* style, GdkWindow* window, 150 GtkStateType state_type, GtkShadowType shadow_type, 151 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 152 gint x, gint y, gint width, gint height); 153 static void (*fp_gtk_paint_flat_box)(GtkStyle* style, GdkWindow* window, 154 GtkStateType state_type, GtkShadowType shadow_type, 155 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 156 gint x, gint y, gint width, gint height); 157 static void (*fp_gtk_paint_check)(GtkStyle* style, GdkWindow* window, 158 GtkStateType state_type, GtkShadowType shadow_type, 159 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 160 gint x, gint y, gint width, gint height); 161 static void (*fp_gtk_paint_option)(GtkStyle* style, GdkWindow* window, 162 GtkStateType state_type, GtkShadowType shadow_type, 163 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 164 gint x, gint y, gint width, gint height); 165 static void (*fp_gtk_paint_box_gap)(GtkStyle* style, GdkWindow* window, 166 GtkStateType state_type, GtkShadowType shadow_type, 167 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 168 gint x, gint y, gint width, gint height, 169 GtkPositionType gap_side, gint gap_x, gint gap_width); 170 static void (*fp_gtk_paint_extension)(GtkStyle* style, GdkWindow* window, 171 GtkStateType state_type, GtkShadowType shadow_type, 172 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 173 gint x, gint y, gint width, gint height, GtkPositionType gap_side); 174 static void (*fp_gtk_paint_focus)(GtkStyle* style, GdkWindow* window, 175 GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, 176 const gchar* detail, gint x, gint y, gint width, gint height); 177 static void (*fp_gtk_paint_slider)(GtkStyle* style, GdkWindow* window, 178 GtkStateType state_type, GtkShadowType shadow_type, 179 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 180 gint x, gint y, gint width, gint height, GtkOrientation orientation); 181 static void (*fp_gtk_paint_handle)(GtkStyle* style, GdkWindow* window, 182 GtkStateType state_type, GtkShadowType shadow_type, 183 GdkRectangle* area, GtkWidget* widget, const gchar* detail, 184 gint x, gint y, gint width, gint height, GtkOrientation orientation); 185 static void (*fp_gtk_paint_expander)(GtkStyle* style, GdkWindow* window, 186 GtkStateType state_type, GdkRectangle* area, GtkWidget* widget, 187 const gchar* detail, gint x, gint y, GtkExpanderStyle expander_style); 188 static void (*fp_gtk_style_apply_default_background)(GtkStyle* style, 189 GdkWindow* window, gboolean set_bg, GtkStateType state_type, 190 GdkRectangle* area, gint x, gint y, gint width, gint height); 191 192 /* Widget creation */ 193 static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type, 194 GtkShadowType shadow_type); 195 static GtkWidget* (*fp_gtk_button_new)(); 196 static GtkWidget* (*fp_gtk_check_button_new)(); 197 static GtkWidget* (*fp_gtk_check_menu_item_new)(); 198 static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title); 199 static GtkWidget* (*fp_gtk_combo_box_new)(); 200 static GtkWidget* (*fp_gtk_combo_box_entry_new)(); 201 static GtkWidget* (*fp_gtk_entry_new)(); 202 static GtkWidget* (*fp_gtk_fixed_new)(); 203 static GtkWidget* (*fp_gtk_handle_box_new)(); 204 static GtkWidget* (*fp_gtk_hpaned_new)(); 205 static GtkWidget* (*fp_gtk_vpaned_new)(); 206 static GtkWidget* (*fp_gtk_hscale_new)(GtkAdjustment* adjustment); 207 static GtkWidget* (*fp_gtk_vscale_new)(GtkAdjustment* adjustment); 208 static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment); 209 static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment); 210 static GtkWidget* (*fp_gtk_hseparator_new)(); 211 static GtkWidget* (*fp_gtk_vseparator_new)(); 212 static GtkWidget* (*fp_gtk_image_new)(); 213 static GtkWidget* (*fp_gtk_label_new)(const gchar* str); 214 static GtkWidget* (*fp_gtk_menu_new)(); 215 static GtkWidget* (*fp_gtk_menu_bar_new)(); 216 static GtkWidget* (*fp_gtk_menu_item_new)(); 217 static GtkWidget* (*fp_gtk_notebook_new)(); 218 static GtkWidget* (*fp_gtk_progress_bar_new)(); 219 static GtkWidget* (*fp_gtk_progress_bar_set_orientation)( 220 GtkProgressBar *pbar, 221 GtkProgressBarOrientation orientation); 222 static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group); 223 static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group); 224 static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment, 225 GtkAdjustment *vadjustment); 226 static GtkWidget* (*fp_gtk_separator_menu_item_new)(); 227 static GtkWidget* (*fp_gtk_separator_tool_item_new)(); 228 static GtkWidget* (*fp_gtk_text_view_new)(); 229 static GtkWidget* (*fp_gtk_toggle_button_new)(); 230 static GtkWidget* (*fp_gtk_toolbar_new)(); 231 static GtkWidget* (*fp_gtk_tree_view_new)(); 232 static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment, 233 GtkAdjustment *vadjustment); 234 static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type); 235 static GtkWidget* (*fp_gtk_dialog_new)(); 236 static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment, 237 gdouble climb_rate, guint digits); 238 static GtkWidget* (*fp_gtk_frame_new)(const gchar *label); 239 240 /* Other widget operations */ 241 static GtkObject* (*fp_gtk_adjustment_new)(gdouble value, 242 gdouble lower, gdouble upper, gdouble step_increment, 243 gdouble page_increment, gdouble page_size); 244 static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget); 245 static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell, 246 GtkWidget *child); 247 static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item, 248 GtkWidget *submenu); 249 static void (*fp_gtk_widget_realize)(GtkWidget *widget); 250 static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget, 251 const gchar *stock_id, GtkIconSize size, const gchar *detail); 252 static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name); 253 static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent); 254 static void (*fp_gtk_widget_set_direction)(GtkWidget *widget, 255 GtkTextDirection direction); 256 static void (*fp_gtk_widget_style_get)(GtkWidget *widget, 257 const gchar *first_property_name, ...); 258 static void (*fp_gtk_widget_class_install_style_property)( 259 GtkWidgetClass* class, GParamSpec *pspec); 260 static GParamSpec* (*fp_gtk_widget_class_find_style_property)( 261 GtkWidgetClass* class, const gchar* property_name); 262 static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget, 263 const gchar* property_name, GValue* value); 264 static char* (*fp_pango_font_description_to_string)( 265 const PangoFontDescription* fd); 266 static GtkSettings* (*fp_gtk_settings_get_default)(); 267 static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget); 268 static GType (*fp_gtk_border_get_type)(); 269 static void (*fp_gtk_arrow_set)(GtkWidget* arrow, 270 GtkArrowType arrow_type, 271 GtkShadowType shadow_type); 272 static void (*fp_gtk_widget_size_request)(GtkWidget *widget, 273 GtkRequisition *requisition); 274 static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range); 275 276 /* Method bodies */ 277 278 static void throw_exception(JNIEnv *env, const char* name, const char* message) 279 { 280 jclass class = (*env)->FindClass(env, name); 281 282 if (class != NULL) 283 (*env)->ThrowNew(env, class, message); 284 285 (*env)->DeleteLocalRef(env, class); 286 } 287 288 /* This is a workaround for the bug: 289 * http://sourceware.org/bugzilla/show_bug.cgi?id=1814 290 * (dlsym/dlopen clears dlerror state) 291 * This bug is specific to Linux, but there is no harm in 292 * applying this workaround on Solaris as well. 293 */ 294 static void* dl_symbol(const char* name) 295 { 296 void* result = dlsym(gtk2_libhandle, name); 297 if (!result) 298 longjmp(j, NO_SYMBOL_EXCEPTION); 299 300 return result; 301 } 302 303 static void* dl_symbol_gthread(const char* name) 304 { 305 void* result = dlsym(gthread_libhandle, name); 306 if (!result) 307 longjmp(j, NO_SYMBOL_EXCEPTION); 308 309 return result; 310 } 311 312 gboolean gtk2_check(const char* lib_name, gboolean load) 313 { 314 if (gtk2_libhandle != NULL) { 315 /* We've already successfully opened the GTK libs, so return true. */ 316 return TRUE; 317 } else { 318 void *lib = NULL; 319 320 #ifdef RTLD_NOLOAD 321 /* Just check if gtk libs are already in the process space */ 322 lib = dlopen(lib_name, RTLD_LAZY | RTLD_NOLOAD); 323 if (!load || lib != NULL) { 324 return lib != NULL; 325 } 326 #else 327 #ifdef _AIX 328 /* On AIX we could implement this with the help of loadquery(L_GETINFO, ..) */ 329 /* (see reload_table() in hotspot/src/os/aix/vm/loadlib_aix.cpp) but it is */ 330 /* probably not worth it because most AIX servers don't have GTK libs anyway */ 331 #endif 332 #endif 333 334 lib = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); 335 if (lib == NULL) { 336 return FALSE; 337 } 338 339 fp_gtk_check_version = dlsym(lib, "gtk_check_version"); 340 /* Check for GTK 2.2+ */ 341 if (!fp_gtk_check_version(2, 2, 0)) { 342 return TRUE; 343 } 344 345 // 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065 346 // dlclose(lib); 347 348 return FALSE; 349 } 350 } 351 352 #define ADD_SUPPORTED_ACTION(actionStr) \ 353 do { \ 354 jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, "Ljava/awt/Desktop$Action;"); \ 355 if (!(*env)->ExceptionCheck(env)) { \ 356 jobject action = (*env)->GetStaticObjectField(env, cls_action, fld_action); \ 357 (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, action); \ 358 } else { \ 359 (*env)->ExceptionClear(env); \ 360 } \ 361 } while(0); 362 363 364 static void update_supported_actions(JNIEnv *env) { 365 GVfs * (*fp_g_vfs_get_default) (void); 366 const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs); 367 const gchar * const * schemes = NULL; 368 369 jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action"); 370 CHECK_NULL(cls_action); 371 jclass cls_xDesktopPeer = (*env)->FindClass(env, "sun/awt/X11/XDesktopPeer"); 372 CHECK_NULL(cls_xDesktopPeer); 373 jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, cls_xDesktopPeer, "supportedActions", "Ljava/util/List;"); 374 CHECK_NULL(fld_supportedActions); 375 jobject supportedActions = (*env)->GetStaticObjectField(env, cls_xDesktopPeer, fld_supportedActions); 376 377 jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList"); 378 CHECK_NULL(cls_arrayList); 379 jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", "(Ljava/lang/Object;)Z"); 380 CHECK_NULL(mid_arrayListAdd); 381 jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, "clear", "()V"); 382 CHECK_NULL(mid_arrayListClear); 383 384 (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear); 385 386 ADD_SUPPORTED_ACTION("OPEN"); 387 388 /** 389 * gtk_show_uri() documentation says: 390 * 391 * > you need to install gvfs to get support for uri schemes such as http:// 392 * > or ftp://, as only local files are handled by GIO itself. 393 * 394 * So OPEN action was safely added here. 395 * However, it looks like Solaris 11 have gvfs support only for 32-bit 396 * applications only by default. 397 */ 398 399 fp_g_vfs_get_default = dl_symbol("g_vfs_get_default"); 400 fp_g_vfs_get_supported_uri_schemes = dl_symbol("g_vfs_get_supported_uri_schemes"); 401 dlerror(); 402 403 if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) { 404 GVfs * vfs = fp_g_vfs_get_default(); 405 schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL; 406 if (schemes) { 407 int i = 0; 408 while (schemes[i]) { 409 if (strcmp(schemes[i], "http") == 0) { 410 ADD_SUPPORTED_ACTION("BROWSE"); 411 ADD_SUPPORTED_ACTION("MAIL"); 412 break; 413 } 414 i++; 415 } 416 } 417 } else { 418 #ifdef DEBUG 419 fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n"); 420 #endif /* DEBUG */ 421 } 422 423 } 424 /** 425 * Functions for awt_Desktop.c 426 */ 427 static gboolean gtk2_show_uri_load(JNIEnv *env) { 428 gboolean success = FALSE; 429 dlerror(); 430 const char *gtk_version = fp_gtk_check_version(2, 14, 0); 431 if (gtk_version != NULL) { 432 // The gtk_show_uri is available from GTK+ 2.14 433 #ifdef DEBUG 434 fprintf (stderr, "The version of GTK is %s. " 435 "The gtk_show_uri function is supported " 436 "since GTK+ 2.14.\n", gtk_version); 437 #endif /* DEBUG */ 438 } else { 439 // Loading symbols only if the GTK version is 2.14 and higher 440 fp_gtk_show_uri = dl_symbol("gtk_show_uri"); 441 const char *dlsym_error = dlerror(); 442 if (dlsym_error) { 443 #ifdef DEBUG 444 fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error); 445 #endif /* DEBUG */ 446 } else if (fp_gtk_show_uri == NULL) { 447 #ifdef DEBUG 448 fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n"); 449 #endif /* DEBUG */ 450 } else { 451 gtk->gtk_show_uri = fp_gtk_show_uri; 452 update_supported_actions(env); 453 success = TRUE; 454 } 455 } 456 return success; 457 } 458 459 /** 460 * Functions for sun_awt_X11_GtkFileDialogPeer.c 461 */ 462 static void gtk2_file_chooser_load() 463 { 464 fp_gtk_file_chooser_get_filename = dl_symbol( 465 "gtk_file_chooser_get_filename"); 466 fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new"); 467 fp_gtk_file_chooser_set_current_folder = dl_symbol( 468 "gtk_file_chooser_set_current_folder"); 469 fp_gtk_file_chooser_set_filename = dl_symbol( 470 "gtk_file_chooser_set_filename"); 471 fp_gtk_file_chooser_set_current_name = dl_symbol( 472 "gtk_file_chooser_set_current_name"); 473 fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom"); 474 fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter"); 475 fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type"); 476 fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new"); 477 if (fp_gtk_check_version(2, 8, 0) == NULL) { 478 fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol( 479 "gtk_file_chooser_set_do_overwrite_confirmation"); 480 } 481 fp_gtk_file_chooser_set_select_multiple = dl_symbol( 482 "gtk_file_chooser_set_select_multiple"); 483 fp_gtk_file_chooser_get_current_folder = dl_symbol( 484 "gtk_file_chooser_get_current_folder"); 485 fp_gtk_file_chooser_get_filenames = dl_symbol( 486 "gtk_file_chooser_get_filenames"); 487 fp_gtk_g_slist_length = dl_symbol("g_slist_length"); 488 fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid"); 489 } 490 491 GtkApi* gtk2_load(JNIEnv *env, const char* lib_name) 492 { 493 gboolean result; 494 int i; 495 int (*handler)(); 496 int (*io_handler)(); 497 char *gtk_modules_env; 498 499 gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); 500 if (gtk2_libhandle == NULL) { 501 return FALSE; 502 } 503 504 gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL); 505 if (gthread_libhandle == NULL) { 506 gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL); 507 if (gthread_libhandle == NULL) 508 return FALSE; 509 } 510 511 if (setjmp(j) == 0) 512 { 513 fp_gtk_check_version = dl_symbol("gtk_check_version"); 514 /* Check for GTK 2.2+ */ 515 if (fp_gtk_check_version(2, 2, 0)) { 516 longjmp(j, NO_SYMBOL_EXCEPTION); 517 } 518 519 /* GLib */ 520 fp_glib_check_version = dlsym(gtk2_libhandle, "glib_check_version"); 521 if (!fp_glib_check_version) { 522 dlerror(); 523 } 524 fp_g_free = dl_symbol("g_free"); 525 fp_g_object_unref = dl_symbol("g_object_unref"); 526 527 fp_g_main_context_iteration = 528 dl_symbol("g_main_context_iteration"); 529 530 fp_g_value_init = dl_symbol("g_value_init"); 531 fp_g_type_is_a = dl_symbol("g_type_is_a"); 532 533 fp_g_value_get_boolean = dl_symbol("g_value_get_boolean"); 534 fp_g_value_get_char = dl_symbol("g_value_get_char"); 535 fp_g_value_get_uchar = dl_symbol("g_value_get_uchar"); 536 fp_g_value_get_int = dl_symbol("g_value_get_int"); 537 fp_g_value_get_uint = dl_symbol("g_value_get_uint"); 538 fp_g_value_get_long = dl_symbol("g_value_get_long"); 539 fp_g_value_get_ulong = dl_symbol("g_value_get_ulong"); 540 fp_g_value_get_int64 = dl_symbol("g_value_get_int64"); 541 fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64"); 542 fp_g_value_get_float = dl_symbol("g_value_get_float"); 543 fp_g_value_get_double = dl_symbol("g_value_get_double"); 544 fp_g_value_get_string = dl_symbol("g_value_get_string"); 545 fp_g_value_get_enum = dl_symbol("g_value_get_enum"); 546 fp_g_value_get_flags = dl_symbol("g_value_get_flags"); 547 fp_g_value_get_param = dl_symbol("g_value_get_param"); 548 fp_g_value_get_boxed = dl_symbol("g_value_get_boxed"); 549 fp_g_value_get_pointer = dl_symbol("g_value_get_pointer"); 550 fp_g_value_get_object = dl_symbol("g_value_get_object"); 551 fp_g_param_spec_int = dl_symbol("g_param_spec_int"); 552 fp_g_object_get = dl_symbol("g_object_get"); 553 fp_g_object_set = dl_symbol("g_object_set"); 554 555 /* GDK */ 556 fp_gdk_get_default_root_window = 557 dl_symbol("gdk_get_default_root_window"); 558 fp_gdk_pixmap_new = dl_symbol("gdk_pixmap_new"); 559 fp_gdk_pixbuf_get_from_drawable = 560 dl_symbol("gdk_pixbuf_get_from_drawable"); 561 fp_gdk_pixbuf_scale_simple = 562 dl_symbol("gdk_pixbuf_scale_simple"); 563 fp_gdk_gc_new = dl_symbol("gdk_gc_new"); 564 fp_gdk_rgb_gc_set_foreground = 565 dl_symbol("gdk_rgb_gc_set_foreground"); 566 fp_gdk_draw_rectangle = dl_symbol("gdk_draw_rectangle"); 567 fp_gdk_drawable_get_size = dl_symbol("gdk_drawable_get_size"); 568 569 /* Pixbuf */ 570 fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new"); 571 fp_gdk_pixbuf_new_from_file = 572 dl_symbol("gdk_pixbuf_new_from_file"); 573 fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width"); 574 fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height"); 575 fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels"); 576 fp_gdk_pixbuf_get_rowstride = 577 dl_symbol("gdk_pixbuf_get_rowstride"); 578 fp_gdk_pixbuf_get_has_alpha = 579 dl_symbol("gdk_pixbuf_get_has_alpha"); 580 fp_gdk_pixbuf_get_bits_per_sample = 581 dl_symbol("gdk_pixbuf_get_bits_per_sample"); 582 fp_gdk_pixbuf_get_n_channels = 583 dl_symbol("gdk_pixbuf_get_n_channels"); 584 fp_gdk_pixbuf_get_colorspace = 585 dl_symbol("gdk_pixbuf_get_colorspace"); 586 587 /* GTK painting */ 588 fp_gtk_init_check = dl_symbol("gtk_init_check"); 589 fp_gtk_paint_hline = dl_symbol("gtk_paint_hline"); 590 fp_gtk_paint_vline = dl_symbol("gtk_paint_vline"); 591 fp_gtk_paint_shadow = dl_symbol("gtk_paint_shadow"); 592 fp_gtk_paint_arrow = dl_symbol("gtk_paint_arrow"); 593 fp_gtk_paint_diamond = dl_symbol("gtk_paint_diamond"); 594 fp_gtk_paint_box = dl_symbol("gtk_paint_box"); 595 fp_gtk_paint_flat_box = dl_symbol("gtk_paint_flat_box"); 596 fp_gtk_paint_check = dl_symbol("gtk_paint_check"); 597 fp_gtk_paint_option = dl_symbol("gtk_paint_option"); 598 fp_gtk_paint_box_gap = dl_symbol("gtk_paint_box_gap"); 599 fp_gtk_paint_extension = dl_symbol("gtk_paint_extension"); 600 fp_gtk_paint_focus = dl_symbol("gtk_paint_focus"); 601 fp_gtk_paint_slider = dl_symbol("gtk_paint_slider"); 602 fp_gtk_paint_handle = dl_symbol("gtk_paint_handle"); 603 fp_gtk_paint_expander = dl_symbol("gtk_paint_expander"); 604 fp_gtk_style_apply_default_background = 605 dl_symbol("gtk_style_apply_default_background"); 606 607 /* GTK widgets */ 608 fp_gtk_arrow_new = dl_symbol("gtk_arrow_new"); 609 fp_gtk_button_new = dl_symbol("gtk_button_new"); 610 fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new"); 611 fp_gtk_check_button_new = dl_symbol("gtk_check_button_new"); 612 fp_gtk_check_menu_item_new = 613 dl_symbol("gtk_check_menu_item_new"); 614 fp_gtk_color_selection_dialog_new = 615 dl_symbol("gtk_color_selection_dialog_new"); 616 fp_gtk_entry_new = dl_symbol("gtk_entry_new"); 617 fp_gtk_fixed_new = dl_symbol("gtk_fixed_new"); 618 fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new"); 619 fp_gtk_image_new = dl_symbol("gtk_image_new"); 620 fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new"); 621 fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new"); 622 fp_gtk_hscale_new = dl_symbol("gtk_hscale_new"); 623 fp_gtk_vscale_new = dl_symbol("gtk_vscale_new"); 624 fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new"); 625 fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new"); 626 fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new"); 627 fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new"); 628 fp_gtk_label_new = dl_symbol("gtk_label_new"); 629 fp_gtk_menu_new = dl_symbol("gtk_menu_new"); 630 fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new"); 631 fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new"); 632 fp_gtk_menu_item_set_submenu = 633 dl_symbol("gtk_menu_item_set_submenu"); 634 fp_gtk_notebook_new = dl_symbol("gtk_notebook_new"); 635 fp_gtk_progress_bar_new = 636 dl_symbol("gtk_progress_bar_new"); 637 fp_gtk_progress_bar_set_orientation = 638 dl_symbol("gtk_progress_bar_set_orientation"); 639 fp_gtk_radio_button_new = 640 dl_symbol("gtk_radio_button_new"); 641 fp_gtk_radio_menu_item_new = 642 dl_symbol("gtk_radio_menu_item_new"); 643 fp_gtk_scrolled_window_new = 644 dl_symbol("gtk_scrolled_window_new"); 645 fp_gtk_separator_menu_item_new = 646 dl_symbol("gtk_separator_menu_item_new"); 647 fp_gtk_text_view_new = dl_symbol("gtk_text_view_new"); 648 fp_gtk_toggle_button_new = 649 dl_symbol("gtk_toggle_button_new"); 650 fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new"); 651 fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new"); 652 fp_gtk_viewport_new = dl_symbol("gtk_viewport_new"); 653 fp_gtk_window_new = dl_symbol("gtk_window_new"); 654 fp_gtk_window_present = dl_symbol("gtk_window_present"); 655 fp_gtk_window_move = dl_symbol("gtk_window_move"); 656 fp_gtk_window_resize = dl_symbol("gtk_window_resize"); 657 658 fp_gtk_dialog_new = dl_symbol("gtk_dialog_new"); 659 fp_gtk_frame_new = dl_symbol("gtk_frame_new"); 660 661 fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new"); 662 fp_gtk_container_add = dl_symbol("gtk_container_add"); 663 fp_gtk_menu_shell_append = 664 dl_symbol("gtk_menu_shell_append"); 665 fp_gtk_widget_realize = dl_symbol("gtk_widget_realize"); 666 fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy"); 667 fp_gtk_widget_render_icon = 668 dl_symbol("gtk_widget_render_icon"); 669 fp_gtk_widget_set_name = 670 dl_symbol("gtk_widget_set_name"); 671 fp_gtk_widget_set_parent = 672 dl_symbol("gtk_widget_set_parent"); 673 fp_gtk_widget_set_direction = 674 dl_symbol("gtk_widget_set_direction"); 675 fp_gtk_widget_style_get = 676 dl_symbol("gtk_widget_style_get"); 677 fp_gtk_widget_class_install_style_property = 678 dl_symbol("gtk_widget_class_install_style_property"); 679 fp_gtk_widget_class_find_style_property = 680 dl_symbol("gtk_widget_class_find_style_property"); 681 fp_gtk_widget_style_get_property = 682 dl_symbol("gtk_widget_style_get_property"); 683 fp_pango_font_description_to_string = 684 dl_symbol("pango_font_description_to_string"); 685 fp_gtk_settings_get_default = 686 dl_symbol("gtk_settings_get_default"); 687 fp_gtk_widget_get_settings = 688 dl_symbol("gtk_widget_get_settings"); 689 fp_gtk_border_get_type = dl_symbol("gtk_border_get_type"); 690 fp_gtk_arrow_set = dl_symbol("gtk_arrow_set"); 691 fp_gtk_widget_size_request = 692 dl_symbol("gtk_widget_size_request"); 693 fp_gtk_range_get_adjustment = 694 dl_symbol("gtk_range_get_adjustment"); 695 696 fp_gtk_widget_hide = dl_symbol("gtk_widget_hide"); 697 fp_gtk_main_quit = dl_symbol("gtk_main_quit"); 698 fp_g_signal_connect_data = dl_symbol("g_signal_connect_data"); 699 fp_gtk_widget_show = dl_symbol("gtk_widget_show"); 700 fp_gtk_main = dl_symbol("gtk_main"); 701 702 fp_g_path_get_dirname = dl_symbol("g_path_get_dirname"); 703 704 /** 705 * GLib thread system 706 */ 707 if (GLIB_CHECK_VERSION(2, 20, 0)) { 708 fp_g_thread_get_initialized = dl_symbol_gthread("g_thread_get_initialized"); 709 } 710 fp_g_thread_init = dl_symbol_gthread("g_thread_init"); 711 fp_gdk_threads_init = dl_symbol("gdk_threads_init"); 712 fp_gdk_threads_enter = dl_symbol("gdk_threads_enter"); 713 fp_gdk_threads_leave = dl_symbol("gdk_threads_leave"); 714 715 /** 716 * Functions for sun_awt_X11_GtkFileDialogPeer.c 717 */ 718 if (fp_gtk_check_version(2, 4, 0) == NULL) { 719 // The current GtkFileChooser is available from GTK+ 2.4 720 gtk2_file_chooser_load(); 721 } 722 723 /* Some functions may be missing in pre-2.4 GTK. 724 We handle them specially here. 725 */ 726 fp_gtk_combo_box_new = dlsym(gtk2_libhandle, "gtk_combo_box_new"); 727 if (fp_gtk_combo_box_new == NULL) { 728 fp_gtk_combo_box_new = dl_symbol("gtk_combo_new"); 729 } 730 731 fp_gtk_combo_box_entry_new = 732 dlsym(gtk2_libhandle, "gtk_combo_box_entry_new"); 733 if (fp_gtk_combo_box_entry_new == NULL) { 734 fp_gtk_combo_box_entry_new = dl_symbol("gtk_combo_new"); 735 new_combo = FALSE; 736 } 737 738 fp_gtk_separator_tool_item_new = 739 dlsym(gtk2_libhandle, "gtk_separator_tool_item_new"); 740 if (fp_gtk_separator_tool_item_new == NULL) { 741 fp_gtk_separator_tool_item_new = 742 dl_symbol("gtk_vseparator_new"); 743 } 744 745 fp_g_list_append = dl_symbol("g_list_append"); 746 fp_g_list_free = dl_symbol("g_list_free"); 747 fp_g_list_free_full = dl_symbol("g_list_free_full"); 748 } 749 /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION 750 * Otherwise we can check the return value of setjmp method. 751 */ 752 else 753 { 754 dlclose(gtk2_libhandle); 755 gtk2_libhandle = NULL; 756 757 dlclose(gthread_libhandle); 758 gthread_libhandle = NULL; 759 760 return FALSE; 761 } 762 763 /* 764 * Strip the AT-SPI GTK_MODULES if present 765 */ 766 gtk_modules_env = getenv ("GTK_MODULES"); 767 if ((gtk_modules_env && strstr(gtk_modules_env, "atk-bridge")) || 768 (gtk_modules_env && strstr(gtk_modules_env, "gail"))) { 769 /* careful, strtok modifies its args */ 770 gchar *tmp_env = strdup(gtk_modules_env); 771 if (tmp_env) { 772 /* the new env will be smaller than the old one */ 773 gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc, 774 sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env)); 775 776 if (new_env) { 777 strcpy(new_env, ENV_PREFIX); 778 779 /* strip out 'atk-bridge' and 'gail' */ 780 size_t PREFIX_LENGTH = strlen(ENV_PREFIX); 781 gchar *tmp_ptr = NULL; 782 for (s = strtok_r(tmp_env, ":", &tmp_ptr); s; 783 s = strtok_r(NULL, ":", &tmp_ptr)) { 784 if ((!strstr(s, "atk-bridge")) && (!strstr(s, "gail"))) { 785 if (strlen(new_env) > PREFIX_LENGTH) { 786 new_env = strcat(new_env, ":"); 787 } 788 new_env = strcat(new_env, s); 789 } 790 } 791 if (putenv(new_env) != 0) { 792 /* no free() on success, putenv() doesn't copy string */ 793 free(new_env); 794 } 795 } 796 free(tmp_env); 797 } 798 } 799 /* 800 * GTK should be initialized with gtk_init_check() before use. 801 * 802 * gtk_init_check installs its own error handlers. It is critical that 803 * we preserve error handler set from AWT. Otherwise we'll crash on 804 * BadMatch errors which we would normally ignore. The IO error handler 805 * is preserved here, too, just for consistency. 806 */ 807 AWT_LOCK(); 808 handler = XSetErrorHandler(NULL); 809 io_handler = XSetIOErrorHandler(NULL); 810 811 if (fp_gtk_check_version(2, 2, 0) == NULL) { 812 813 // Calling g_thread_init() multiple times leads to crash on GLib < 2.24 814 // We can use g_thread_get_initialized () but it is available only for 815 // GLib >= 2.20. 816 gboolean is_g_thread_get_initialized = FALSE; 817 if (GLIB_CHECK_VERSION(2, 20, 0)) { 818 is_g_thread_get_initialized = fp_g_thread_get_initialized(); 819 } 820 821 if (!is_g_thread_get_initialized) { 822 fp_g_thread_init(NULL); 823 } 824 825 //According the GTK documentation, gdk_threads_init() should be 826 //called before gtk_init() or gtk_init_check() 827 fp_gdk_threads_init(); 828 } 829 result = (*fp_gtk_init_check)(NULL, NULL); 830 831 XSetErrorHandler(handler); 832 XSetIOErrorHandler(io_handler); 833 AWT_UNLOCK(); 834 835 /* Initialize widget array. */ 836 for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++) 837 { 838 gtk2_widgets[i] = NULL; 839 } 840 if (result) { 841 GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi)); 842 gtk2_init(gtk); 843 return gtk; 844 } 845 return NULL; 846 } 847 848 int gtk2_unload() 849 { 850 int i; 851 char *gtk2_error; 852 853 if (!gtk2_libhandle) 854 return TRUE; 855 856 /* Release painting objects */ 857 if (gtk2_white_pixmap != NULL) { 858 (*fp_g_object_unref)(gtk2_white_pixmap); 859 (*fp_g_object_unref)(gtk2_black_pixmap); 860 (*fp_g_object_unref)(gtk2_white_pixbuf); 861 (*fp_g_object_unref)(gtk2_black_pixbuf); 862 gtk2_white_pixmap = gtk2_black_pixmap = 863 gtk2_white_pixbuf = gtk2_black_pixbuf = NULL; 864 } 865 gtk2_pixbuf_width = 0; 866 gtk2_pixbuf_height = 0; 867 868 if (gtk2_window != NULL) { 869 /* Destroying toplevel widget will destroy all contained widgets */ 870 (*fp_gtk_widget_destroy)(gtk2_window); 871 872 /* Unset some static data so they get reinitialized on next load */ 873 gtk2_window = NULL; 874 } 875 876 dlerror(); 877 dlclose(gtk2_libhandle); 878 dlclose(gthread_libhandle); 879 if ((gtk2_error = dlerror()) != NULL) 880 { 881 return FALSE; 882 } 883 return TRUE; 884 } 885 886 /* Dispatch all pending events from the GTK event loop. 887 * This is needed to catch theme change and update widgets' style. 888 */ 889 static void flush_gtk_event_loop() 890 { 891 while( (*fp_g_main_context_iteration)(NULL, FALSE)); 892 } 893 894 /* 895 * Initialize components of containment hierarchy. This creates a GtkFixed 896 * inside a GtkWindow. All widgets get realized. 897 */ 898 static void init_containers() 899 { 900 if (gtk2_window == NULL) 901 { 902 gtk2_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); 903 gtk2_fixed = (GtkFixed *)(*fp_gtk_fixed_new)(); 904 (*fp_gtk_container_add)((GtkContainer*)gtk2_window, 905 (GtkWidget *)gtk2_fixed); 906 (*fp_gtk_widget_realize)(gtk2_window); 907 (*fp_gtk_widget_realize)((GtkWidget *)gtk2_fixed); 908 } 909 } 910 911 /* 912 * Ensure everything is ready for drawing an element of the specified width 913 * and height. 914 * 915 * We should somehow handle translucent images. GTK can draw to X Drawables 916 * only, which don't support alpha. When we retrieve the image back from 917 * the server, translucency information is lost. There're several ways to 918 * work around this: 919 * 1) Subclass GdkPixmap and cache translucent objects on client side. This 920 * requires us to implement parts of X server drawing logic on client side. 921 * Many X requests can potentially be "translucent"; e.g. XDrawLine with 922 * fill=tile and a translucent tile is a "translucent" operation, whereas 923 * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some 924 * do) intermix transparent and opaque operations which makes caching even 925 * more problematic. 926 * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support 927 * for it (as of version 2.6). Also even in JDS 3 Xorg does not support 928 * these visuals by default, which makes optimizing for them pointless. 929 * We can consider doing this at a later point when ARGB visuals become more 930 * popular. 931 * 3') GTK has plans to use Cairo as its graphical backend (presumably in 932 * 2.8), and Cairo supports alpha. With it we could also get rid of the 933 * unnecessary round trip to server and do all the drawing on client side. 934 * 4) For now we draw to two different pixmaps and restore alpha channel by 935 * comparing results. This can be optimized by using subclassed pixmap and 936 * doing the second drawing only if necessary. 937 */ 938 static void gtk2_init_painting(JNIEnv *env, gint width, gint height) 939 { 940 GdkGC *gc; 941 GdkPixbuf *white, *black; 942 943 init_containers(); 944 945 if (gtk2_pixbuf_width < width || gtk2_pixbuf_height < height) 946 { 947 white = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height); 948 black = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height); 949 950 if (white == NULL || black == NULL) 951 { 952 snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height); 953 throw_exception(env, "java/lang/RuntimeException", convertionBuffer); 954 fp_gdk_threads_leave(); 955 return; 956 } 957 958 if (gtk2_white_pixmap != NULL) { 959 /* free old stuff */ 960 (*fp_g_object_unref)(gtk2_white_pixmap); 961 (*fp_g_object_unref)(gtk2_black_pixmap); 962 (*fp_g_object_unref)(gtk2_white_pixbuf); 963 (*fp_g_object_unref)(gtk2_black_pixbuf); 964 } 965 966 gtk2_white_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1); 967 gtk2_black_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1); 968 969 gtk2_white_pixbuf = white; 970 gtk2_black_pixbuf = black; 971 972 gtk2_pixbuf_width = width; 973 gtk2_pixbuf_height = height; 974 } 975 976 /* clear the pixmaps */ 977 gc = (*fp_gdk_gc_new)(gtk2_white_pixmap); 978 (*fp_gdk_rgb_gc_set_foreground)(gc, 0xffffff); 979 (*fp_gdk_draw_rectangle)(gtk2_white_pixmap, gc, TRUE, 0, 0, width, height); 980 (*fp_g_object_unref)(gc); 981 982 gc = (*fp_gdk_gc_new)(gtk2_black_pixmap); 983 (*fp_gdk_rgb_gc_set_foreground)(gc, 0x000000); 984 (*fp_gdk_draw_rectangle)(gtk2_black_pixmap, gc, TRUE, 0, 0, width, height); 985 (*fp_g_object_unref)(gc); 986 } 987 988 /* 989 * Restore image from white and black pixmaps and copy it into destination 990 * buffer. This method compares two pixbufs taken from white and black 991 * pixmaps and decodes color and alpha components. Pixbufs are RGB without 992 * alpha, destination buffer is ABGR. 993 * 994 * The return value is the transparency type of the resulting image, either 995 * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and 996 * java_awt_Transparency_TRANSLUCENT. 997 */ 998 static gint gtk2_copy_image(gint *dst, gint width, gint height) 999 { 1000 gint i, j, r, g, b; 1001 guchar *white, *black; 1002 gint stride, padding; 1003 gboolean is_opaque = TRUE; 1004 gboolean is_bitmask = TRUE; 1005 1006 (*fp_gdk_pixbuf_get_from_drawable)(gtk2_white_pixbuf, gtk2_white_pixmap, 1007 NULL, 0, 0, 0, 0, width, height); 1008 (*fp_gdk_pixbuf_get_from_drawable)(gtk2_black_pixbuf, gtk2_black_pixmap, 1009 NULL, 0, 0, 0, 0, width, height); 1010 1011 white = (*fp_gdk_pixbuf_get_pixels)(gtk2_white_pixbuf); 1012 black = (*fp_gdk_pixbuf_get_pixels)(gtk2_black_pixbuf); 1013 stride = (*fp_gdk_pixbuf_get_rowstride)(gtk2_black_pixbuf); 1014 padding = stride - width * 4; 1015 1016 for (i = 0; i < height; i++) { 1017 for (j = 0; j < width; j++) { 1018 int r1 = *white++; 1019 int r2 = *black++; 1020 int alpha = 0xff + r2 - r1; 1021 1022 switch (alpha) { 1023 case 0: /* transparent pixel */ 1024 r = g = b = 0; 1025 black += 3; 1026 white += 3; 1027 is_opaque = FALSE; 1028 break; 1029 1030 case 0xff: /* opaque pixel */ 1031 r = r2; 1032 g = *black++; 1033 b = *black++; 1034 black++; 1035 white += 3; 1036 break; 1037 1038 default: /* translucent pixel */ 1039 r = 0xff * r2 / alpha; 1040 g = 0xff * *black++ / alpha; 1041 b = 0xff * *black++ / alpha; 1042 black++; 1043 white += 3; 1044 is_opaque = FALSE; 1045 is_bitmask = FALSE; 1046 break; 1047 } 1048 1049 *dst++ = (alpha << 24 | r << 16 | g << 8 | b); 1050 } 1051 1052 white += padding; 1053 black += padding; 1054 } 1055 return is_opaque ? java_awt_Transparency_OPAQUE : 1056 (is_bitmask ? java_awt_Transparency_BITMASK : 1057 java_awt_Transparency_TRANSLUCENT); 1058 } 1059 1060 static void 1061 gtk2_set_direction(GtkWidget *widget, GtkTextDirection dir) 1062 { 1063 /* 1064 * Some engines (inexplicably) look at the direction of the widget's 1065 * parent, so we need to set the direction of both the widget and its 1066 * parent. 1067 */ 1068 (*fp_gtk_widget_set_direction)(widget, dir); 1069 if (widget->parent != NULL) { 1070 (*fp_gtk_widget_set_direction)(widget->parent, dir); 1071 } 1072 } 1073 1074 /* 1075 * Initializes the widget to correct state for some engines. 1076 * This is a pure empirical method. 1077 */ 1078 static void init_toggle_widget(WidgetType widget_type, gint synth_state) 1079 { 1080 gboolean is_active = ((synth_state & SELECTED) != 0); 1081 1082 if (widget_type == RADIO_BUTTON || 1083 widget_type == CHECK_BOX || 1084 widget_type == TOGGLE_BUTTON) { 1085 ((GtkToggleButton*)gtk2_widget)->active = is_active; 1086 } 1087 1088 if ((synth_state & FOCUSED) != 0) { 1089 ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS; 1090 } else { 1091 ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS; 1092 } 1093 1094 if ((synth_state & MOUSE_OVER) != 0 && (synth_state & PRESSED) == 0 || 1095 (synth_state & FOCUSED) != 0 && (synth_state & PRESSED) != 0) { 1096 gtk2_widget->state = GTK_STATE_PRELIGHT; 1097 } else if ((synth_state & DISABLED) != 0) { 1098 gtk2_widget->state = GTK_STATE_INSENSITIVE; 1099 } else { 1100 gtk2_widget->state = is_active ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL; 1101 } 1102 } 1103 1104 /* GTK state_type filter */ 1105 static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state) 1106 { 1107 GtkStateType result = GTK_STATE_NORMAL; 1108 1109 if ((synth_state & DISABLED) != 0) { 1110 result = GTK_STATE_INSENSITIVE; 1111 } else if ((synth_state & PRESSED) != 0) { 1112 result = GTK_STATE_ACTIVE; 1113 } else if ((synth_state & MOUSE_OVER) != 0) { 1114 result = GTK_STATE_PRELIGHT; 1115 } 1116 return result; 1117 } 1118 1119 /* GTK shadow_type filter */ 1120 static GtkShadowType get_gtk_shadow_type(WidgetType widget_type, gint synth_state) 1121 { 1122 GtkShadowType result = GTK_SHADOW_OUT; 1123 1124 if ((synth_state & SELECTED) != 0) { 1125 result = GTK_SHADOW_IN; 1126 } 1127 return result; 1128 } 1129 1130 1131 static GtkWidget* gtk2_get_arrow(GtkArrowType arrow_type, GtkShadowType shadow_type) 1132 { 1133 GtkWidget *arrow = NULL; 1134 if (NULL == gtk2_widgets[_GTK_ARROW_TYPE]) 1135 { 1136 gtk2_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type, shadow_type); 1137 (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, gtk2_widgets[_GTK_ARROW_TYPE]); 1138 (*fp_gtk_widget_realize)(gtk2_widgets[_GTK_ARROW_TYPE]); 1139 } 1140 arrow = gtk2_widgets[_GTK_ARROW_TYPE]; 1141 1142 (*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type); 1143 return arrow; 1144 } 1145 1146 static GtkAdjustment* create_adjustment() 1147 { 1148 return (GtkAdjustment *) 1149 (*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0); 1150 } 1151 1152 /** 1153 * Returns a pointer to the cached native widget for the specified widget 1154 * type. 1155 */ 1156 static GtkWidget *gtk2_get_widget(WidgetType widget_type) 1157 { 1158 gboolean init_result = FALSE; 1159 GtkWidget *result = NULL; 1160 switch (widget_type) 1161 { 1162 case BUTTON: 1163 case TABLE_HEADER: 1164 if (init_result = (NULL == gtk2_widgets[_GTK_BUTTON_TYPE])) 1165 { 1166 gtk2_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)(); 1167 } 1168 result = gtk2_widgets[_GTK_BUTTON_TYPE]; 1169 break; 1170 case CHECK_BOX: 1171 if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_BUTTON_TYPE])) 1172 { 1173 gtk2_widgets[_GTK_CHECK_BUTTON_TYPE] = 1174 (*fp_gtk_check_button_new)(); 1175 } 1176 result = gtk2_widgets[_GTK_CHECK_BUTTON_TYPE]; 1177 break; 1178 case CHECK_BOX_MENU_ITEM: 1179 if (init_result = (NULL == gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE])) 1180 { 1181 gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE] = 1182 (*fp_gtk_check_menu_item_new)(); 1183 } 1184 result = gtk2_widgets[_GTK_CHECK_MENU_ITEM_TYPE]; 1185 break; 1186 /************************************************************ 1187 * Creation a dedicated color chooser is dangerous because 1188 * it deadlocks the EDT 1189 ************************************************************/ 1190 /* case COLOR_CHOOSER: 1191 if (init_result = 1192 (NULL == gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE])) 1193 { 1194 gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] = 1195 (*fp_gtk_color_selection_dialog_new)(NULL); 1196 } 1197 result = gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]; 1198 break;*/ 1199 case COMBO_BOX: 1200 if (init_result = (NULL == gtk2_widgets[_GTK_COMBO_BOX_TYPE])) 1201 { 1202 gtk2_widgets[_GTK_COMBO_BOX_TYPE] = 1203 (*fp_gtk_combo_box_new)(); 1204 } 1205 result = gtk2_widgets[_GTK_COMBO_BOX_TYPE]; 1206 break; 1207 case COMBO_BOX_ARROW_BUTTON: 1208 if (init_result = 1209 (NULL == gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE])) 1210 { 1211 gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] = 1212 (*fp_gtk_toggle_button_new)(); 1213 } 1214 result = gtk2_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]; 1215 break; 1216 case COMBO_BOX_TEXT_FIELD: 1217 if (init_result = 1218 (NULL == gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE])) 1219 { 1220 result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] = 1221 (*fp_gtk_entry_new)(); 1222 } 1223 result = gtk2_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]; 1224 break; 1225 case DESKTOP_ICON: 1226 case INTERNAL_FRAME_TITLE_PANE: 1227 case LABEL: 1228 if (init_result = (NULL == gtk2_widgets[_GTK_LABEL_TYPE])) 1229 { 1230 gtk2_widgets[_GTK_LABEL_TYPE] = 1231 (*fp_gtk_label_new)(NULL); 1232 } 1233 result = gtk2_widgets[_GTK_LABEL_TYPE]; 1234 break; 1235 case DESKTOP_PANE: 1236 case PANEL: 1237 case ROOT_PANE: 1238 if (init_result = (NULL == gtk2_widgets[_GTK_CONTAINER_TYPE])) 1239 { 1240 /* There is no constructor for a container type. I've 1241 * chosen GtkFixed container since it has a default 1242 * constructor. 1243 */ 1244 gtk2_widgets[_GTK_CONTAINER_TYPE] = 1245 (*fp_gtk_fixed_new)(); 1246 } 1247 result = gtk2_widgets[_GTK_CONTAINER_TYPE]; 1248 break; 1249 case EDITOR_PANE: 1250 case TEXT_AREA: 1251 case TEXT_PANE: 1252 if (init_result = (NULL == gtk2_widgets[_GTK_TEXT_VIEW_TYPE])) 1253 { 1254 gtk2_widgets[_GTK_TEXT_VIEW_TYPE] = 1255 (*fp_gtk_text_view_new)(); 1256 } 1257 result = gtk2_widgets[_GTK_TEXT_VIEW_TYPE]; 1258 break; 1259 case FORMATTED_TEXT_FIELD: 1260 case PASSWORD_FIELD: 1261 case TEXT_FIELD: 1262 if (init_result = (NULL == gtk2_widgets[_GTK_ENTRY_TYPE])) 1263 { 1264 gtk2_widgets[_GTK_ENTRY_TYPE] = 1265 (*fp_gtk_entry_new)(); 1266 } 1267 result = gtk2_widgets[_GTK_ENTRY_TYPE]; 1268 break; 1269 case HANDLE_BOX: 1270 if (init_result = (NULL == gtk2_widgets[_GTK_HANDLE_BOX_TYPE])) 1271 { 1272 gtk2_widgets[_GTK_HANDLE_BOX_TYPE] = 1273 (*fp_gtk_handle_box_new)(); 1274 } 1275 result = gtk2_widgets[_GTK_HANDLE_BOX_TYPE]; 1276 break; 1277 case HSCROLL_BAR: 1278 case HSCROLL_BAR_BUTTON_LEFT: 1279 case HSCROLL_BAR_BUTTON_RIGHT: 1280 case HSCROLL_BAR_TRACK: 1281 case HSCROLL_BAR_THUMB: 1282 if (init_result = (NULL == gtk2_widgets[_GTK_HSCROLLBAR_TYPE])) 1283 { 1284 gtk2_widgets[_GTK_HSCROLLBAR_TYPE] = 1285 (*fp_gtk_hscrollbar_new)(create_adjustment()); 1286 } 1287 result = gtk2_widgets[_GTK_HSCROLLBAR_TYPE]; 1288 break; 1289 case HSEPARATOR: 1290 if (init_result = (NULL == gtk2_widgets[_GTK_HSEPARATOR_TYPE])) 1291 { 1292 gtk2_widgets[_GTK_HSEPARATOR_TYPE] = 1293 (*fp_gtk_hseparator_new)(); 1294 } 1295 result = gtk2_widgets[_GTK_HSEPARATOR_TYPE]; 1296 break; 1297 case HSLIDER: 1298 case HSLIDER_THUMB: 1299 case HSLIDER_TRACK: 1300 if (init_result = (NULL == gtk2_widgets[_GTK_HSCALE_TYPE])) 1301 { 1302 gtk2_widgets[_GTK_HSCALE_TYPE] = 1303 (*fp_gtk_hscale_new)(NULL); 1304 } 1305 result = gtk2_widgets[_GTK_HSCALE_TYPE]; 1306 break; 1307 case HSPLIT_PANE_DIVIDER: 1308 case SPLIT_PANE: 1309 if (init_result = (NULL == gtk2_widgets[_GTK_HPANED_TYPE])) 1310 { 1311 gtk2_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)(); 1312 } 1313 result = gtk2_widgets[_GTK_HPANED_TYPE]; 1314 break; 1315 case IMAGE: 1316 if (init_result = (NULL == gtk2_widgets[_GTK_IMAGE_TYPE])) 1317 { 1318 gtk2_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)(); 1319 } 1320 result = gtk2_widgets[_GTK_IMAGE_TYPE]; 1321 break; 1322 case INTERNAL_FRAME: 1323 if (init_result = (NULL == gtk2_widgets[_GTK_WINDOW_TYPE])) 1324 { 1325 gtk2_widgets[_GTK_WINDOW_TYPE] = 1326 (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); 1327 } 1328 result = gtk2_widgets[_GTK_WINDOW_TYPE]; 1329 break; 1330 case TOOL_TIP: 1331 if (init_result = (NULL == gtk2_widgets[_GTK_TOOLTIP_TYPE])) 1332 { 1333 result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL); 1334 (*fp_gtk_widget_set_name)(result, "gtk-tooltips"); 1335 gtk2_widgets[_GTK_TOOLTIP_TYPE] = result; 1336 } 1337 result = gtk2_widgets[_GTK_TOOLTIP_TYPE]; 1338 break; 1339 case LIST: 1340 case TABLE: 1341 case TREE: 1342 case TREE_CELL: 1343 if (init_result = (NULL == gtk2_widgets[_GTK_TREE_VIEW_TYPE])) 1344 { 1345 gtk2_widgets[_GTK_TREE_VIEW_TYPE] = 1346 (*fp_gtk_tree_view_new)(); 1347 } 1348 result = gtk2_widgets[_GTK_TREE_VIEW_TYPE]; 1349 break; 1350 case TITLED_BORDER: 1351 if (init_result = (NULL == gtk2_widgets[_GTK_FRAME_TYPE])) 1352 { 1353 gtk2_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL); 1354 } 1355 result = gtk2_widgets[_GTK_FRAME_TYPE]; 1356 break; 1357 case POPUP_MENU: 1358 if (init_result = (NULL == gtk2_widgets[_GTK_MENU_TYPE])) 1359 { 1360 gtk2_widgets[_GTK_MENU_TYPE] = 1361 (*fp_gtk_menu_new)(); 1362 } 1363 result = gtk2_widgets[_GTK_MENU_TYPE]; 1364 break; 1365 case MENU: 1366 case MENU_ITEM: 1367 case MENU_ITEM_ACCELERATOR: 1368 if (init_result = (NULL == gtk2_widgets[_GTK_MENU_ITEM_TYPE])) 1369 { 1370 gtk2_widgets[_GTK_MENU_ITEM_TYPE] = 1371 (*fp_gtk_menu_item_new)(); 1372 } 1373 result = gtk2_widgets[_GTK_MENU_ITEM_TYPE]; 1374 break; 1375 case MENU_BAR: 1376 if (init_result = (NULL == gtk2_widgets[_GTK_MENU_BAR_TYPE])) 1377 { 1378 gtk2_widgets[_GTK_MENU_BAR_TYPE] = 1379 (*fp_gtk_menu_bar_new)(); 1380 } 1381 result = gtk2_widgets[_GTK_MENU_BAR_TYPE]; 1382 break; 1383 case COLOR_CHOOSER: 1384 case OPTION_PANE: 1385 if (init_result = (NULL == gtk2_widgets[_GTK_DIALOG_TYPE])) 1386 { 1387 gtk2_widgets[_GTK_DIALOG_TYPE] = 1388 (*fp_gtk_dialog_new)(); 1389 } 1390 result = gtk2_widgets[_GTK_DIALOG_TYPE]; 1391 break; 1392 case POPUP_MENU_SEPARATOR: 1393 if (init_result = 1394 (NULL == gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE])) 1395 { 1396 gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] = 1397 (*fp_gtk_separator_menu_item_new)(); 1398 } 1399 result = gtk2_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]; 1400 break; 1401 case HPROGRESS_BAR: 1402 if (init_result = (NULL == gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE])) 1403 { 1404 gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE] = 1405 (*fp_gtk_progress_bar_new)(); 1406 } 1407 result = gtk2_widgets[_GTK_HPROGRESS_BAR_TYPE]; 1408 break; 1409 case VPROGRESS_BAR: 1410 if (init_result = (NULL == gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE])) 1411 { 1412 gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE] = 1413 (*fp_gtk_progress_bar_new)(); 1414 /* 1415 * Vertical JProgressBars always go bottom-to-top, 1416 * regardless of the ComponentOrientation. 1417 */ 1418 (*fp_gtk_progress_bar_set_orientation)( 1419 (GtkProgressBar *)gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE], 1420 GTK_PROGRESS_BOTTOM_TO_TOP); 1421 } 1422 result = gtk2_widgets[_GTK_VPROGRESS_BAR_TYPE]; 1423 break; 1424 case RADIO_BUTTON: 1425 if (init_result = (NULL == gtk2_widgets[_GTK_RADIO_BUTTON_TYPE])) 1426 { 1427 gtk2_widgets[_GTK_RADIO_BUTTON_TYPE] = 1428 (*fp_gtk_radio_button_new)(NULL); 1429 } 1430 result = gtk2_widgets[_GTK_RADIO_BUTTON_TYPE]; 1431 break; 1432 case RADIO_BUTTON_MENU_ITEM: 1433 if (init_result = 1434 (NULL == gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE])) 1435 { 1436 gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE] = 1437 (*fp_gtk_radio_menu_item_new)(NULL); 1438 } 1439 result = gtk2_widgets[_GTK_RADIO_MENU_ITEM_TYPE]; 1440 break; 1441 case SCROLL_PANE: 1442 if (init_result = 1443 (NULL == gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE])) 1444 { 1445 gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE] = 1446 (*fp_gtk_scrolled_window_new)(NULL, NULL); 1447 } 1448 result = gtk2_widgets[_GTK_SCROLLED_WINDOW_TYPE]; 1449 break; 1450 case SPINNER: 1451 case SPINNER_ARROW_BUTTON: 1452 case SPINNER_TEXT_FIELD: 1453 if (init_result = (NULL == gtk2_widgets[_GTK_SPIN_BUTTON_TYPE])) 1454 { 1455 result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE] = 1456 (*fp_gtk_spin_button_new)(NULL, 0, 0); 1457 } 1458 result = gtk2_widgets[_GTK_SPIN_BUTTON_TYPE]; 1459 break; 1460 case TABBED_PANE: 1461 case TABBED_PANE_TAB_AREA: 1462 case TABBED_PANE_CONTENT: 1463 case TABBED_PANE_TAB: 1464 if (init_result = (NULL == gtk2_widgets[_GTK_NOTEBOOK_TYPE])) 1465 { 1466 gtk2_widgets[_GTK_NOTEBOOK_TYPE] = 1467 (*fp_gtk_notebook_new)(NULL); 1468 } 1469 result = gtk2_widgets[_GTK_NOTEBOOK_TYPE]; 1470 break; 1471 case TOGGLE_BUTTON: 1472 if (init_result = (NULL == gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE])) 1473 { 1474 gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE] = 1475 (*fp_gtk_toggle_button_new)(NULL); 1476 } 1477 result = gtk2_widgets[_GTK_TOGGLE_BUTTON_TYPE]; 1478 break; 1479 case TOOL_BAR: 1480 case TOOL_BAR_DRAG_WINDOW: 1481 if (init_result = (NULL == gtk2_widgets[_GTK_TOOLBAR_TYPE])) 1482 { 1483 gtk2_widgets[_GTK_TOOLBAR_TYPE] = 1484 (*fp_gtk_toolbar_new)(NULL); 1485 } 1486 result = gtk2_widgets[_GTK_TOOLBAR_TYPE]; 1487 break; 1488 case TOOL_BAR_SEPARATOR: 1489 if (init_result = 1490 (NULL == gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE])) 1491 { 1492 gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] = 1493 (*fp_gtk_separator_tool_item_new)(); 1494 } 1495 result = gtk2_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]; 1496 break; 1497 case VIEWPORT: 1498 if (init_result = (NULL == gtk2_widgets[_GTK_VIEWPORT_TYPE])) 1499 { 1500 GtkAdjustment *adjustment = create_adjustment(); 1501 gtk2_widgets[_GTK_VIEWPORT_TYPE] = 1502 (*fp_gtk_viewport_new)(adjustment, adjustment); 1503 } 1504 result = gtk2_widgets[_GTK_VIEWPORT_TYPE]; 1505 break; 1506 case VSCROLL_BAR: 1507 case VSCROLL_BAR_BUTTON_UP: 1508 case VSCROLL_BAR_BUTTON_DOWN: 1509 case VSCROLL_BAR_TRACK: 1510 case VSCROLL_BAR_THUMB: 1511 if (init_result = (NULL == gtk2_widgets[_GTK_VSCROLLBAR_TYPE])) 1512 { 1513 gtk2_widgets[_GTK_VSCROLLBAR_TYPE] = 1514 (*fp_gtk_vscrollbar_new)(create_adjustment()); 1515 } 1516 result = gtk2_widgets[_GTK_VSCROLLBAR_TYPE]; 1517 break; 1518 case VSEPARATOR: 1519 if (init_result = (NULL == gtk2_widgets[_GTK_VSEPARATOR_TYPE])) 1520 { 1521 gtk2_widgets[_GTK_VSEPARATOR_TYPE] = 1522 (*fp_gtk_vseparator_new)(); 1523 } 1524 result = gtk2_widgets[_GTK_VSEPARATOR_TYPE]; 1525 break; 1526 case VSLIDER: 1527 case VSLIDER_THUMB: 1528 case VSLIDER_TRACK: 1529 if (init_result = (NULL == gtk2_widgets[_GTK_VSCALE_TYPE])) 1530 { 1531 gtk2_widgets[_GTK_VSCALE_TYPE] = 1532 (*fp_gtk_vscale_new)(NULL); 1533 } 1534 result = gtk2_widgets[_GTK_VSCALE_TYPE]; 1535 /* 1536 * Vertical JSliders start at the bottom, while vertical 1537 * GtkVScale widgets start at the top (by default), so to fix 1538 * this we set the "inverted" flag to get the Swing behavior. 1539 */ 1540 ((GtkRange*)result)->inverted = 1; 1541 break; 1542 case VSPLIT_PANE_DIVIDER: 1543 if (init_result = (NULL == gtk2_widgets[_GTK_VPANED_TYPE])) 1544 { 1545 gtk2_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)(); 1546 } 1547 result = gtk2_widgets[_GTK_VPANED_TYPE]; 1548 break; 1549 default: 1550 result = NULL; 1551 break; 1552 } 1553 1554 if (result != NULL && init_result) 1555 { 1556 if (widget_type == RADIO_BUTTON_MENU_ITEM || 1557 widget_type == CHECK_BOX_MENU_ITEM || 1558 widget_type == MENU_ITEM || 1559 widget_type == MENU || 1560 widget_type == POPUP_MENU_SEPARATOR) 1561 { 1562 GtkWidget *menu = gtk2_get_widget(POPUP_MENU); 1563 (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result); 1564 } 1565 else if (widget_type == POPUP_MENU) 1566 { 1567 GtkWidget *menu_bar = gtk2_get_widget(MENU_BAR); 1568 GtkWidget *root_menu = (*fp_gtk_menu_item_new)(); 1569 (*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result); 1570 (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu); 1571 } 1572 else if (widget_type == COMBO_BOX_ARROW_BUTTON || 1573 widget_type == COMBO_BOX_TEXT_FIELD) 1574 { 1575 /* 1576 * We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry 1577 * in order to trick engines into thinking it's a real combobox 1578 * arrow button/text field. 1579 */ 1580 GtkWidget *combo = (*fp_gtk_combo_box_entry_new)(); 1581 1582 if (new_combo && widget_type == COMBO_BOX_ARROW_BUTTON) { 1583 (*fp_gtk_widget_set_parent)(result, combo); 1584 ((GtkBin*)combo)->child = result; 1585 } else { 1586 (*fp_gtk_container_add)((GtkContainer *)combo, result); 1587 } 1588 (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, combo); 1589 } 1590 else if (widget_type != TOOL_TIP && 1591 widget_type != INTERNAL_FRAME && 1592 widget_type != OPTION_PANE) 1593 { 1594 (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, result); 1595 } 1596 (*fp_gtk_widget_realize)(result); 1597 } 1598 return result; 1599 } 1600 1601 void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type, 1602 GtkShadowType shadow_type, const gchar *detail, 1603 gint x, gint y, gint width, gint height, 1604 GtkArrowType arrow_type, gboolean fill) 1605 { 1606 static int w, h; 1607 static GtkRequisition size; 1608 1609 if (widget_type == COMBO_BOX_ARROW_BUTTON || widget_type == TABLE) 1610 gtk2_widget = gtk2_get_arrow(arrow_type, shadow_type); 1611 else 1612 gtk2_widget = gtk2_get_widget(widget_type); 1613 1614 switch (widget_type) 1615 { 1616 case SPINNER_ARROW_BUTTON: 1617 x = 1; 1618 y = ((arrow_type == GTK_ARROW_UP) ? 2 : 0); 1619 height -= 2; 1620 width -= 3; 1621 1622 w = width / 2; 1623 w -= w % 2 - 1; 1624 h = (w + 1) / 2; 1625 break; 1626 1627 case HSCROLL_BAR_BUTTON_LEFT: 1628 case HSCROLL_BAR_BUTTON_RIGHT: 1629 case VSCROLL_BAR_BUTTON_UP: 1630 case VSCROLL_BAR_BUTTON_DOWN: 1631 w = width / 2; 1632 h = height / 2; 1633 break; 1634 1635 case COMBO_BOX_ARROW_BUTTON: 1636 case TABLE: 1637 x = 1; 1638 (*fp_gtk_widget_size_request)(gtk2_widget, &size); 1639 w = size.width - ((GtkMisc*)gtk2_widget)->xpad * 2; 1640 h = size.height - ((GtkMisc*)gtk2_widget)->ypad * 2; 1641 w = h = MIN(MIN(w, h), MIN(width,height)) * 0.7; 1642 break; 1643 1644 default: 1645 w = width; 1646 h = height; 1647 break; 1648 } 1649 x += (width - w) / 2; 1650 y += (height - h) / 2; 1651 1652 (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1653 shadow_type, NULL, gtk2_widget, detail, arrow_type, fill, 1654 x, y, w, h); 1655 (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1656 shadow_type, NULL, gtk2_widget, detail, arrow_type, fill, 1657 x, y, w, h); 1658 } 1659 1660 static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type, 1661 GtkShadowType shadow_type, const gchar *detail, 1662 gint x, gint y, gint width, gint height, 1663 gint synth_state, GtkTextDirection dir) 1664 { 1665 gtk2_widget = gtk2_get_widget(widget_type); 1666 1667 /* 1668 * The clearlooks engine sometimes looks at the widget's state field 1669 * instead of just the state_type variable that we pass in, so to account 1670 * for those cases we set the widget's state field accordingly. The 1671 * flags field is similarly important for things like focus/default state. 1672 */ 1673 gtk2_widget->state = state_type; 1674 1675 if (widget_type == HSLIDER_TRACK) { 1676 /* 1677 * For horizontal JSliders with right-to-left orientation, we need 1678 * to set the "inverted" flag to match the native GTK behavior where 1679 * the foreground highlight is on the right side of the slider thumb. 1680 * This is needed especially for the ubuntulooks engine, which looks 1681 * exclusively at the "inverted" flag to determine on which side of 1682 * the thumb to paint the highlight... 1683 */ 1684 ((GtkRange*)gtk2_widget)->inverted = (dir == GTK_TEXT_DIR_RTL); 1685 1686 /* 1687 * Note however that other engines like clearlooks will look at both 1688 * the "inverted" field and the text direction to determine how 1689 * the foreground highlight is painted: 1690 * !inverted && ltr --> paint highlight on left side 1691 * !inverted && rtl --> paint highlight on right side 1692 * inverted && ltr --> paint highlight on right side 1693 * inverted && rtl --> paint highlight on left side 1694 * So the only way to reliably get the desired results for horizontal 1695 * JSlider (i.e., highlight on left side for LTR ComponentOrientation 1696 * and highlight on right side for RTL ComponentOrientation) is to 1697 * always override text direction as LTR, and then set the "inverted" 1698 * flag accordingly (as we have done above). 1699 */ 1700 dir = GTK_TEXT_DIR_LTR; 1701 } 1702 1703 /* 1704 * Some engines (e.g. clearlooks) will paint the shadow of certain 1705 * widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the 1706 * the text direction. 1707 */ 1708 gtk2_set_direction(gtk2_widget, dir); 1709 1710 switch (widget_type) { 1711 case BUTTON: 1712 if (synth_state & DEFAULT) { 1713 ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_DEFAULT; 1714 } else { 1715 ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_DEFAULT; 1716 } 1717 break; 1718 case TOGGLE_BUTTON: 1719 init_toggle_widget(widget_type, synth_state); 1720 break; 1721 case HSCROLL_BAR_BUTTON_LEFT: 1722 /* 1723 * The clearlooks engine will draw a "left" button when: 1724 * x == w->allocation.x 1725 * 1726 * The ubuntulooks engine will draw a "left" button when: 1727 * [x,y,width,height] 1728 * intersects 1729 * [w->alloc.x,w->alloc.y,width,height] 1730 * 1731 * The values that are set below should ensure that a "left" 1732 * button is rendered for both of these (and other) engines. 1733 */ 1734 gtk2_widget->allocation.x = x; 1735 gtk2_widget->allocation.y = y; 1736 gtk2_widget->allocation.width = width; 1737 gtk2_widget->allocation.height = height; 1738 break; 1739 case HSCROLL_BAR_BUTTON_RIGHT: 1740 /* 1741 * The clearlooks engine will draw a "right" button when: 1742 * x + width == w->allocation.x + w->allocation.width 1743 * 1744 * The ubuntulooks engine will draw a "right" button when: 1745 * [x,y,width,height] 1746 * does not intersect 1747 * [w->alloc.x,w->alloc.y,width,height] 1748 * but does intersect 1749 * [w->alloc.x+width,w->alloc.y,width,height] 1750 * 1751 * The values that are set below should ensure that a "right" 1752 * button is rendered for both of these (and other) engines. 1753 */ 1754 gtk2_widget->allocation.x = x+width; 1755 gtk2_widget->allocation.y = 0; 1756 gtk2_widget->allocation.width = 0; 1757 gtk2_widget->allocation.height = height; 1758 break; 1759 case VSCROLL_BAR_BUTTON_UP: 1760 /* 1761 * The clearlooks engine will draw an "up" button when: 1762 * y == w->allocation.y 1763 * 1764 * The ubuntulooks engine will draw an "up" button when: 1765 * [x,y,width,height] 1766 * intersects 1767 * [w->alloc.x,w->alloc.y,width,height] 1768 * 1769 * The values that are set below should ensure that an "up" 1770 * button is rendered for both of these (and other) engines. 1771 */ 1772 gtk2_widget->allocation.x = x; 1773 gtk2_widget->allocation.y = y; 1774 gtk2_widget->allocation.width = width; 1775 gtk2_widget->allocation.height = height; 1776 break; 1777 case VSCROLL_BAR_BUTTON_DOWN: 1778 /* 1779 * The clearlooks engine will draw a "down" button when: 1780 * y + height == w->allocation.y + w->allocation.height 1781 * 1782 * The ubuntulooks engine will draw a "down" button when: 1783 * [x,y,width,height] 1784 * does not intersect 1785 * [w->alloc.x,w->alloc.y,width,height] 1786 * but does intersect 1787 * [w->alloc.x,w->alloc.y+height,width,height] 1788 * 1789 * The values that are set below should ensure that a "down" 1790 * button is rendered for both of these (and other) engines. 1791 */ 1792 gtk2_widget->allocation.x = x; 1793 gtk2_widget->allocation.y = y+height; 1794 gtk2_widget->allocation.width = width; 1795 gtk2_widget->allocation.height = 0; 1796 break; 1797 default: 1798 break; 1799 } 1800 1801 (*fp_gtk_paint_box)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1802 shadow_type, NULL, gtk2_widget, detail, x, y, width, height); 1803 (*fp_gtk_paint_box)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1804 shadow_type, NULL, gtk2_widget, detail, x, y, width, height); 1805 1806 /* 1807 * Reset the text direction to the default value so that we don't 1808 * accidentally affect other operations and widgets. 1809 */ 1810 gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR); 1811 } 1812 1813 void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type, 1814 GtkShadowType shadow_type, const gchar *detail, 1815 gint x, gint y, gint width, gint height, 1816 GtkPositionType gap_side, gint gap_x, gint gap_width) 1817 { 1818 /* Clearlooks needs a real clip area to paint the gap properly */ 1819 GdkRectangle area = { x, y, width, height }; 1820 1821 gtk2_widget = gtk2_get_widget(widget_type); 1822 (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1823 shadow_type, &area, gtk2_widget, detail, 1824 x, y, width, height, gap_side, gap_x, gap_width); 1825 (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1826 shadow_type, &area, gtk2_widget, detail, 1827 x, y, width, height, gap_side, gap_x, gap_width); 1828 } 1829 1830 static void gtk2_paint_check(WidgetType widget_type, gint synth_state, 1831 const gchar *detail, gint x, gint y, gint width, gint height) 1832 { 1833 GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); 1834 GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state); 1835 1836 gtk2_widget = gtk2_get_widget(widget_type); 1837 init_toggle_widget(widget_type, synth_state); 1838 1839 (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1840 shadow_type, NULL, gtk2_widget, detail, 1841 x, y, width, height); 1842 (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1843 shadow_type, NULL, gtk2_widget, detail, 1844 x, y, width, height); 1845 } 1846 1847 static void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type, 1848 GtkShadowType shadow_type, const gchar *detail, 1849 gint x, gint y, gint width, gint height) 1850 { 1851 gtk2_widget = gtk2_get_widget(widget_type); 1852 (*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1853 shadow_type, NULL, gtk2_widget, detail, 1854 x, y, width, height); 1855 (*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1856 shadow_type, NULL, gtk2_widget, detail, 1857 x, y, width, height); 1858 } 1859 1860 static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type, 1861 const gchar *detail, gint x, gint y, gint width, gint height, 1862 GtkExpanderStyle expander_style) 1863 { 1864 gtk2_widget = gtk2_get_widget(widget_type); 1865 (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_white_pixmap, 1866 state_type, NULL, gtk2_widget, detail, 1867 x + width / 2, y + height / 2, expander_style); 1868 (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_black_pixmap, 1869 state_type, NULL, gtk2_widget, detail, 1870 x + width / 2, y + height / 2, expander_style); 1871 } 1872 1873 static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type, 1874 GtkShadowType shadow_type, const gchar *detail, 1875 gint x, gint y, gint width, gint height, GtkPositionType gap_side) 1876 { 1877 gtk2_widget = gtk2_get_widget(widget_type); 1878 (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_white_pixmap, 1879 state_type, shadow_type, NULL, gtk2_widget, detail, 1880 x, y, width, height, gap_side); 1881 (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_black_pixmap, 1882 state_type, shadow_type, NULL, gtk2_widget, detail, 1883 x, y, width, height, gap_side); 1884 } 1885 1886 static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type, 1887 GtkShadowType shadow_type, const gchar *detail, 1888 gint x, gint y, gint width, gint height, gboolean has_focus) 1889 { 1890 gtk2_widget = gtk2_get_widget(widget_type); 1891 1892 if (has_focus) 1893 ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS; 1894 else 1895 ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS; 1896 1897 (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_white_pixmap, 1898 state_type, shadow_type, NULL, gtk2_widget, detail, 1899 x, y, width, height); 1900 (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_black_pixmap, 1901 state_type, shadow_type, NULL, gtk2_widget, detail, 1902 x, y, width, height); 1903 } 1904 1905 static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type, 1906 const char *detail, gint x, gint y, gint width, gint height) 1907 { 1908 gtk2_widget = gtk2_get_widget(widget_type); 1909 (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1910 NULL, gtk2_widget, detail, x, y, width, height); 1911 (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1912 NULL, gtk2_widget, detail, x, y, width, height); 1913 } 1914 1915 static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type, 1916 GtkShadowType shadow_type, const gchar *detail, 1917 gint x, gint y, gint width, gint height, GtkOrientation orientation) 1918 { 1919 gtk2_widget = gtk2_get_widget(widget_type); 1920 (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1921 shadow_type, NULL, gtk2_widget, detail, 1922 x, y, width, height, orientation); 1923 (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1924 shadow_type, NULL, gtk2_widget, detail, 1925 x, y, width, height, orientation); 1926 } 1927 1928 static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type, 1929 const gchar *detail, gint x, gint y, gint width, gint height) 1930 { 1931 gtk2_widget = gtk2_get_widget(widget_type); 1932 (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1933 NULL, gtk2_widget, detail, x, x + width, y); 1934 (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1935 NULL, gtk2_widget, detail, x, x + width, y); 1936 } 1937 1938 static void gtk2_paint_option(WidgetType widget_type, gint synth_state, 1939 const gchar *detail, gint x, gint y, gint width, gint height) 1940 { 1941 GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); 1942 GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state); 1943 1944 gtk2_widget = gtk2_get_widget(widget_type); 1945 init_toggle_widget(widget_type, synth_state); 1946 1947 (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1948 shadow_type, NULL, gtk2_widget, detail, 1949 x, y, width, height); 1950 (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1951 shadow_type, NULL, gtk2_widget, detail, 1952 x, y, width, height); 1953 } 1954 1955 static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, 1956 GtkShadowType shadow_type, const gchar *detail, 1957 gint x, gint y, gint width, gint height, 1958 gint synth_state, GtkTextDirection dir) 1959 { 1960 gtk2_widget = gtk2_get_widget(widget_type); 1961 1962 /* 1963 * The clearlooks engine sometimes looks at the widget's state field 1964 * instead of just the state_type variable that we pass in, so to account 1965 * for those cases we set the widget's state field accordingly. The 1966 * flags field is similarly important for things like focus state. 1967 */ 1968 gtk2_widget->state = state_type; 1969 1970 /* 1971 * Some engines (e.g. clearlooks) will paint the shadow of certain 1972 * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the 1973 * the text direction. 1974 */ 1975 gtk2_set_direction(gtk2_widget, dir); 1976 1977 switch (widget_type) { 1978 case COMBO_BOX_TEXT_FIELD: 1979 case FORMATTED_TEXT_FIELD: 1980 case PASSWORD_FIELD: 1981 case SPINNER_TEXT_FIELD: 1982 case TEXT_FIELD: 1983 if (synth_state & FOCUSED) { 1984 ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS; 1985 } else { 1986 ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS; 1987 } 1988 break; 1989 default: 1990 break; 1991 } 1992 1993 (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_white_pixmap, state_type, 1994 shadow_type, NULL, gtk2_widget, detail, x, y, width, height); 1995 (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_black_pixmap, state_type, 1996 shadow_type, NULL, gtk2_widget, detail, x, y, width, height); 1997 1998 /* 1999 * Reset the text direction to the default value so that we don't 2000 * accidentally affect other operations and widgets. 2001 */ 2002 gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR); 2003 } 2004 2005 static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type, 2006 GtkShadowType shadow_type, const gchar *detail, 2007 gint x, gint y, gint width, gint height, GtkOrientation orientation, 2008 gboolean has_focus) 2009 { 2010 gtk2_widget = gtk2_get_widget(widget_type); 2011 (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type, 2012 shadow_type, NULL, gtk2_widget, detail, 2013 x, y, width, height, orientation); 2014 (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_black_pixmap, state_type, 2015 shadow_type, NULL, gtk2_widget, detail, 2016 x, y, width, height, orientation); 2017 } 2018 2019 static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type, 2020 const gchar *detail, gint x, gint y, gint width, gint height) 2021 { 2022 gtk2_widget = gtk2_get_widget(widget_type); 2023 (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_white_pixmap, state_type, 2024 NULL, gtk2_widget, detail, y, y + height, x); 2025 (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_black_pixmap, state_type, 2026 NULL, gtk2_widget, detail, y, y + height, x); 2027 } 2028 2029 static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type, 2030 gint x, gint y, gint width, gint height) 2031 { 2032 gtk2_widget = gtk2_get_widget(widget_type); 2033 (*fp_gtk_style_apply_default_background)(gtk2_widget->style, 2034 gtk2_white_pixmap, TRUE, state_type, NULL, x, y, width, height); 2035 (*fp_gtk_style_apply_default_background)(gtk2_widget->style, 2036 gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height); 2037 } 2038 2039 static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id, 2040 GtkIconSize size, GtkTextDirection direction, const char *detail) 2041 { 2042 init_containers(); 2043 gtk2_widget = gtk2_get_widget((widget_type < 0) ? IMAGE : widget_type); 2044 gtk2_widget->state = GTK_STATE_NORMAL; 2045 (*fp_gtk_widget_set_direction)(gtk2_widget, direction); 2046 return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail); 2047 } 2048 2049 static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf, 2050 jmethodID icon_upcall_method, jobject this) { 2051 if (!pixbuf) { 2052 return JNI_FALSE; 2053 } 2054 guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf); 2055 if (pixbuf_data) { 2056 int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); 2057 int width = (*fp_gdk_pixbuf_get_width)(pixbuf); 2058 int height = (*fp_gdk_pixbuf_get_height)(pixbuf); 2059 int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf); 2060 int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); 2061 gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf); 2062 2063 jbyteArray data = (*env)->NewByteArray(env, (row_stride * height)); 2064 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); 2065 2066 (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height), 2067 (jbyte *)pixbuf_data); 2068 (*fp_g_object_unref)(pixbuf); 2069 2070 /* Call the callback method to create the image on the Java side. */ 2071 (*env)->CallVoidMethod(env, this, icon_upcall_method, data, 2072 width, height, row_stride, bps, channels, alpha); 2073 return JNI_TRUE; 2074 } 2075 return JNI_FALSE; 2076 } 2077 2078 static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename, 2079 GError **error, jmethodID icon_upcall_method, jobject this) { 2080 GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error); 2081 return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); 2082 } 2083 2084 static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type, 2085 const gchar *stock_id, GtkIconSize size, 2086 GtkTextDirection direction, const char *detail, 2087 jmethodID icon_upcall_method, jobject this) { 2088 GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size, 2089 direction, detail); 2090 return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this); 2091 } 2092 2093 /*************************************************/ 2094 static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type) 2095 { 2096 init_containers(); 2097 2098 gtk2_widget = gtk2_get_widget(widget_type); 2099 GtkStyle* style = gtk2_widget->style; 2100 return style->xthickness; 2101 } 2102 2103 static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type) 2104 { 2105 init_containers(); 2106 2107 gtk2_widget = gtk2_get_widget(widget_type); 2108 GtkStyle* style = gtk2_widget->style; 2109 return style->ythickness; 2110 } 2111 2112 /*************************************************/ 2113 static guint8 recode_color(guint16 channel) 2114 { 2115 return (guint8)(channel>>8); 2116 } 2117 2118 static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type, 2119 GtkStateType state_type, ColorType color_type) 2120 { 2121 gint result = 0; 2122 GdkColor *color = NULL; 2123 2124 init_containers(); 2125 2126 gtk2_widget = gtk2_get_widget(widget_type); 2127 GtkStyle* style = gtk2_widget->style; 2128 2129 switch (color_type) 2130 { 2131 case FOREGROUND: 2132 color = &(style->fg[state_type]); 2133 break; 2134 case BACKGROUND: 2135 color = &(style->bg[state_type]); 2136 break; 2137 case TEXT_FOREGROUND: 2138 color = &(style->text[state_type]); 2139 break; 2140 case TEXT_BACKGROUND: 2141 color = &(style->base[state_type]); 2142 break; 2143 case LIGHT: 2144 color = &(style->light[state_type]); 2145 break; 2146 case DARK: 2147 color = &(style->dark[state_type]); 2148 break; 2149 case MID: 2150 color = &(style->mid[state_type]); 2151 break; 2152 case FOCUS: 2153 case BLACK: 2154 color = &(style->black); 2155 break; 2156 case WHITE: 2157 color = &(style->white); 2158 break; 2159 } 2160 2161 if (color) 2162 result = recode_color(color->red) << 16 | 2163 recode_color(color->green) << 8 | 2164 recode_color(color->blue); 2165 2166 return result; 2167 } 2168 2169 /*************************************************/ 2170 static jobject create_Boolean(JNIEnv *env, jboolean boolean_value); 2171 static jobject create_Integer(JNIEnv *env, jint int_value); 2172 static jobject create_Long(JNIEnv *env, jlong long_value); 2173 static jobject create_Float(JNIEnv *env, jfloat float_value); 2174 static jobject create_Double(JNIEnv *env, jdouble double_value); 2175 static jobject create_Character(JNIEnv *env, jchar char_value); 2176 static jobject create_Insets(JNIEnv *env, GtkBorder *border); 2177 2178 static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, 2179 const char* key) 2180 { 2181 init_containers(); 2182 2183 gtk2_widget = gtk2_get_widget(widget_type); 2184 2185 GValue value; 2186 value.g_type = 0; 2187 2188 GParamSpec* param = (*fp_gtk_widget_class_find_style_property)( 2189 ((GTypeInstance*)gtk2_widget)->g_class, key); 2190 if( param ) 2191 { 2192 (*fp_g_value_init)( &value, param->value_type ); 2193 (*fp_gtk_widget_style_get_property)(gtk2_widget, key, &value); 2194 2195 if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN )) 2196 { 2197 gboolean val = (*fp_g_value_get_boolean)(&value); 2198 return create_Boolean(env, (jboolean)val); 2199 } 2200 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR )) 2201 { 2202 gchar val = (*fp_g_value_get_char)(&value); 2203 return create_Character(env, (jchar)val); 2204 } 2205 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR )) 2206 { 2207 guchar val = (*fp_g_value_get_uchar)(&value); 2208 return create_Character(env, (jchar)val); 2209 } 2210 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT )) 2211 { 2212 gint val = (*fp_g_value_get_int)(&value); 2213 return create_Integer(env, (jint)val); 2214 } 2215 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT )) 2216 { 2217 guint val = (*fp_g_value_get_uint)(&value); 2218 return create_Integer(env, (jint)val); 2219 } 2220 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_LONG )) 2221 { 2222 glong val = (*fp_g_value_get_long)(&value); 2223 return create_Long(env, (jlong)val); 2224 } 2225 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG )) 2226 { 2227 gulong val = (*fp_g_value_get_ulong)(&value); 2228 return create_Long(env, (jlong)val); 2229 } 2230 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 )) 2231 { 2232 gint64 val = (*fp_g_value_get_int64)(&value); 2233 return create_Long(env, (jlong)val); 2234 } 2235 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 )) 2236 { 2237 guint64 val = (*fp_g_value_get_uint64)(&value); 2238 return create_Long(env, (jlong)val); 2239 } 2240 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT )) 2241 { 2242 gfloat val = (*fp_g_value_get_float)(&value); 2243 return create_Float(env, (jfloat)val); 2244 } 2245 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE )) 2246 { 2247 gdouble val = (*fp_g_value_get_double)(&value); 2248 return create_Double(env, (jdouble)val); 2249 } 2250 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM )) 2251 { 2252 gint val = (*fp_g_value_get_enum)(&value); 2253 return create_Integer(env, (jint)val); 2254 } 2255 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS )) 2256 { 2257 guint val = (*fp_g_value_get_flags)(&value); 2258 return create_Integer(env, (jint)val); 2259 } 2260 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_STRING )) 2261 { 2262 const gchar* val = (*fp_g_value_get_string)(&value); 2263 2264 /* We suppose that all values come in C locale and 2265 * utf-8 representation of a string is the same as 2266 * the string itself. If this isn't so we should 2267 * use g_convert. 2268 */ 2269 return (*env)->NewStringUTF(env, val); 2270 } 2271 else if( (*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER )) 2272 { 2273 GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value); 2274 return border ? create_Insets(env, border) : NULL; 2275 } 2276 2277 /* TODO: Other types are not supported yet.*/ 2278 /* else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM )) 2279 { 2280 GParamSpec* val = (*fp_g_value_get_param)(&value); 2281 printf( "Param: %p\n", val ); 2282 } 2283 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED )) 2284 { 2285 gpointer* val = (*fp_g_value_get_boxed)(&value); 2286 printf( "Boxed: %p\n", val ); 2287 } 2288 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER )) 2289 { 2290 gpointer* val = (*fp_g_value_get_pointer)(&value); 2291 printf( "Pointer: %p\n", val ); 2292 } 2293 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT )) 2294 { 2295 GObject* val = (GObject*)(*fp_g_value_get_object)(&value); 2296 printf( "Object: %p\n", val ); 2297 }*/ 2298 } 2299 2300 return NULL; 2301 } 2302 2303 static void gtk2_set_range_value(WidgetType widget_type, jdouble value, 2304 jdouble min, jdouble max, jdouble visible) 2305 { 2306 GtkAdjustment *adj; 2307 2308 gtk2_widget = gtk2_get_widget(widget_type); 2309 2310 adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk2_widget); 2311 adj->value = (gdouble)value; 2312 adj->lower = (gdouble)min; 2313 adj->upper = (gdouble)max; 2314 adj->page_size = (gdouble)visible; 2315 } 2316 2317 /*************************************************/ 2318 static jobject create_Object(JNIEnv *env, jmethodID *cid, 2319 const char* class_name, 2320 const char* signature, 2321 jvalue* value) 2322 { 2323 jclass class; 2324 jobject result; 2325 2326 class = (*env)->FindClass(env, class_name); 2327 if( class == NULL ) 2328 return NULL; /* can't find/load the class, exception thrown */ 2329 2330 if( *cid == NULL) 2331 { 2332 *cid = (*env)->GetMethodID(env, class, "<init>", signature); 2333 if( *cid == NULL ) 2334 { 2335 (*env)->DeleteLocalRef(env, class); 2336 return NULL; /* can't find/get the method, exception thrown */ 2337 } 2338 } 2339 2340 result = (*env)->NewObjectA(env, class, *cid, value); 2341 2342 (*env)->DeleteLocalRef(env, class); 2343 return result; 2344 } 2345 2346 jobject create_Boolean(JNIEnv *env, jboolean boolean_value) 2347 { 2348 static jmethodID cid = NULL; 2349 jvalue value; 2350 2351 value.z = boolean_value; 2352 2353 return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value); 2354 } 2355 2356 jobject create_Integer(JNIEnv *env, jint int_value) 2357 { 2358 static jmethodID cid = NULL; 2359 jvalue value; 2360 2361 value.i = int_value; 2362 2363 return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value); 2364 } 2365 2366 jobject create_Long(JNIEnv *env, jlong long_value) 2367 { 2368 static jmethodID cid = NULL; 2369 jvalue value; 2370 2371 value.j = long_value; 2372 2373 return create_Object(env, &cid, "java/lang/Long", "(J)V", &value); 2374 } 2375 2376 jobject create_Float(JNIEnv *env, jfloat float_value) 2377 { 2378 static jmethodID cid = NULL; 2379 jvalue value; 2380 2381 value.f = float_value; 2382 2383 return create_Object(env, &cid, "java/lang/Float", "(F)V", &value); 2384 } 2385 2386 jobject create_Double(JNIEnv *env, jdouble double_value) 2387 { 2388 static jmethodID cid = NULL; 2389 jvalue value; 2390 2391 value.d = double_value; 2392 2393 return create_Object(env, &cid, "java/lang/Double", "(D)V", &value); 2394 } 2395 2396 jobject create_Character(JNIEnv *env, jchar char_value) 2397 { 2398 static jmethodID cid = NULL; 2399 jvalue value; 2400 2401 value.c = char_value; 2402 2403 return create_Object(env, &cid, "java/lang/Character", "(C)V", &value); 2404 } 2405 2406 2407 jobject create_Insets(JNIEnv *env, GtkBorder *border) 2408 { 2409 static jmethodID cid = NULL; 2410 jvalue values[4]; 2411 2412 values[0].i = border->top; 2413 values[1].i = border->left; 2414 values[2].i = border->bottom; 2415 values[3].i = border->right; 2416 2417 return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values); 2418 } 2419 2420 /*********************************************/ 2421 static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type) 2422 { 2423 init_containers(); 2424 2425 gtk2_widget = gtk2_get_widget(widget_type); 2426 jstring result = NULL; 2427 GtkStyle* style = gtk2_widget->style; 2428 2429 if (style && style->font_desc) 2430 { 2431 gchar* val = (*fp_pango_font_description_to_string)(style->font_desc); 2432 result = (*env)->NewStringUTF(env, val); 2433 (*fp_g_free)( val ); 2434 } 2435 2436 return result; 2437 } 2438 2439 /***********************************************/ 2440 static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key) 2441 { 2442 jobject result = NULL; 2443 gchar* strval = NULL; 2444 2445 (*fp_g_object_get)(settings, key, &strval, NULL); 2446 result = (*env)->NewStringUTF(env, strval); 2447 (*fp_g_free)(strval); 2448 2449 return result; 2450 } 2451 2452 static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key) 2453 { 2454 gint intval = NULL; 2455 (*fp_g_object_get)(settings, key, &intval, NULL); 2456 return create_Integer(env, intval); 2457 } 2458 2459 static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key) 2460 { 2461 gint intval = NULL; 2462 (*fp_g_object_get)(settings, key, &intval, NULL); 2463 return create_Boolean(env, intval); 2464 } 2465 2466 static jobject gtk2_get_setting(JNIEnv *env, Setting property) 2467 { 2468 GtkSettings* settings = (*fp_gtk_settings_get_default)(); 2469 2470 switch (property) 2471 { 2472 case GTK_FONT_NAME: 2473 return get_string_property(env, settings, "gtk-font-name"); 2474 case GTK_ICON_SIZES: 2475 return get_string_property(env, settings, "gtk-icon-sizes"); 2476 case GTK_CURSOR_BLINK: 2477 return get_boolean_property(env, settings, "gtk-cursor-blink"); 2478 case GTK_CURSOR_BLINK_TIME: 2479 return get_integer_property(env, settings, "gtk-cursor-blink-time"); 2480 } 2481 2482 return NULL; 2483 } 2484 2485 static gboolean gtk2_get_drawable_data(JNIEnv *env, jintArray pixelArray, jint x, 2486 jint y, jint width, jint height, jint jwidth, int dx, int dy, jint scale) { 2487 GdkPixbuf *pixbuf; 2488 jint *ary; 2489 2490 GdkWindow *root = (*fp_gdk_get_default_root_window)(); 2491 2492 pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, x, y, 2493 0, 0, width, height); 2494 if (pixbuf && scale != 1) { 2495 GdkPixbuf *scaledPixbuf; 2496 x /= scale; 2497 y /= scale; 2498 width /= scale; 2499 height /= scale; 2500 dx /= scale; 2501 dy /= scale; 2502 scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height, 2503 GDK_INTERP_BILINEAR); 2504 (*fp_g_object_unref)(pixbuf); 2505 pixbuf = scaledPixbuf; 2506 } 2507 2508 if (pixbuf) { 2509 int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf); 2510 int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf); 2511 2512 if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width 2513 && (*fp_gdk_pixbuf_get_height)(pixbuf) == height 2514 && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8 2515 && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB 2516 && nchan >= 3 2517 ) { 2518 guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf); 2519 2520 ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL); 2521 if (ary) { 2522 jint _x, _y; 2523 int index; 2524 for (_y = 0; _y < height; _y++) { 2525 for (_x = 0; _x < width; _x++) { 2526 p = pix + _y * stride + _x * nchan; 2527 2528 index = (_y + dy) * jwidth + (_x + dx); 2529 ary[index] = 0xff000000 2530 | (p[0] << 16) 2531 | (p[1] << 8) 2532 | (p[2]); 2533 2534 } 2535 } 2536 (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0); 2537 } 2538 } 2539 (*fp_g_object_unref)(pixbuf); 2540 } 2541 return JNI_FALSE; 2542 } 2543 2544 static GdkWindow* gtk2_get_window(void *widget) { 2545 return ((GtkWidget*)widget)->window; 2546 } 2547 2548 void gtk2_init(GtkApi* gtk) { 2549 gtk->version = GTK_2; 2550 2551 gtk->show_uri_load = >k2_show_uri_load; 2552 gtk->unload = >k2_unload; 2553 gtk->flush_event_loop = &flush_gtk_event_loop; 2554 gtk->gtk_check_version = fp_gtk_check_version; 2555 gtk->get_setting = >k2_get_setting; 2556 2557 gtk->paint_arrow = >k2_paint_arrow; 2558 gtk->paint_box = >k2_paint_box; 2559 gtk->paint_box_gap = >k2_paint_box_gap; 2560 gtk->paint_expander = >k2_paint_expander; 2561 gtk->paint_extension = >k2_paint_extension; 2562 gtk->paint_flat_box = >k2_paint_flat_box; 2563 gtk->paint_focus = >k2_paint_focus; 2564 gtk->paint_handle = >k2_paint_handle; 2565 gtk->paint_hline = >k2_paint_hline; 2566 gtk->paint_vline = >k2_paint_vline; 2567 gtk->paint_option = >k2_paint_option; 2568 gtk->paint_shadow = >k2_paint_shadow; 2569 gtk->paint_slider = >k2_paint_slider; 2570 gtk->paint_background = >k_paint_background; 2571 gtk->paint_check = >k2_paint_check; 2572 gtk->set_range_value = >k2_set_range_value; 2573 2574 gtk->init_painting = >k2_init_painting; 2575 gtk->copy_image = >k2_copy_image; 2576 2577 gtk->get_xthickness = >k2_get_xthickness; 2578 gtk->get_ythickness = >k2_get_ythickness; 2579 gtk->get_color_for_state = >k2_get_color_for_state; 2580 gtk->get_class_value = >k2_get_class_value; 2581 2582 gtk->get_pango_font_name = >k2_get_pango_font_name; 2583 gtk->get_icon_data = >k2_get_icon_data; 2584 gtk->get_file_icon_data = >k2_get_file_icon_data; 2585 gtk->gdk_threads_enter = fp_gdk_threads_enter; 2586 gtk->gdk_threads_leave = fp_gdk_threads_leave; 2587 gtk->gtk_show_uri = fp_gtk_show_uri; 2588 gtk->get_drawable_data = >k2_get_drawable_data; 2589 gtk->g_free = fp_g_free; 2590 2591 gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename; 2592 gtk->gtk_widget_hide = fp_gtk_widget_hide; 2593 gtk->gtk_main_quit = fp_gtk_main_quit; 2594 gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new; 2595 gtk->gtk_file_chooser_set_current_folder = 2596 fp_gtk_file_chooser_set_current_folder; 2597 gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename; 2598 gtk->gtk_file_chooser_set_current_name = 2599 fp_gtk_file_chooser_set_current_name; 2600 gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom; 2601 gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter; 2602 gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type; 2603 gtk->gtk_file_filter_new = fp_gtk_file_filter_new; 2604 gtk->gtk_file_chooser_set_do_overwrite_confirmation = 2605 fp_gtk_file_chooser_set_do_overwrite_confirmation; 2606 gtk->gtk_file_chooser_set_select_multiple = 2607 fp_gtk_file_chooser_set_select_multiple; 2608 gtk->gtk_file_chooser_get_current_folder = 2609 fp_gtk_file_chooser_get_current_folder; 2610 gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames; 2611 gtk->gtk_g_slist_length = fp_gtk_g_slist_length; 2612 gtk->g_signal_connect_data = fp_g_signal_connect_data; 2613 gtk->gtk_widget_show = fp_gtk_widget_show; 2614 gtk->gtk_main = fp_gtk_main; 2615 gtk->gtk_main_level = fp_gtk_main_level; 2616 gtk->g_path_get_dirname = fp_g_path_get_dirname; 2617 gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid; 2618 gtk->gtk_widget_destroy = fp_gtk_widget_destroy; 2619 gtk->gtk_window_present = fp_gtk_window_present; 2620 gtk->gtk_window_move = fp_gtk_window_move; 2621 gtk->gtk_window_resize = fp_gtk_window_resize; 2622 gtk->get_window = >k2_get_window; 2623 2624 gtk->g_object_unref = fp_g_object_unref; 2625 gtk->g_list_append = fp_g_list_append; 2626 gtk->g_list_free = fp_g_list_free; 2627 gtk->g_list_free_full = fp_g_list_free_full; 2628 }