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