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