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