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