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