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