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