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