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