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