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