src/solaris/native/sun/awt/gtk2_interface.c

Print this page




  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)


  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=";


 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);


 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,


 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,


 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 


 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 


 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)


 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()




  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 #include <dlfcn.h>
  26 #include <setjmp.h>
  27 #include <X11/Xlib.h>
  28 #include <limits.h>
  29 #include <stdio.h>
  30 #include <string.h>
  31 #include "gtk2_interface.h"
  32 #include "java_awt_Transparency.h"
  33 
  34 #define GTK2_LIB "libgtk-x11-2.0.so.0"
  35 #define GTHREAD_LIB "libgthread-2.0.so.0"
  36 
  37 #define G_TYPE_INVALID                  G_TYPE_MAKE_FUNDAMENTAL (0)
  38 #define G_TYPE_NONE                     G_TYPE_MAKE_FUNDAMENTAL (1)
  39 #define G_TYPE_INTERFACE                G_TYPE_MAKE_FUNDAMENTAL (2)
  40 #define G_TYPE_CHAR                     G_TYPE_MAKE_FUNDAMENTAL (3)
  41 #define G_TYPE_UCHAR                    G_TYPE_MAKE_FUNDAMENTAL (4)
  42 #define G_TYPE_BOOLEAN                  G_TYPE_MAKE_FUNDAMENTAL (5)
  43 #define G_TYPE_INT                      G_TYPE_MAKE_FUNDAMENTAL (6)
  44 #define G_TYPE_UINT                     G_TYPE_MAKE_FUNDAMENTAL (7)
  45 #define G_TYPE_LONG                     G_TYPE_MAKE_FUNDAMENTAL (8)
  46 #define G_TYPE_ULONG                    G_TYPE_MAKE_FUNDAMENTAL (9)
  47 #define G_TYPE_INT64                    G_TYPE_MAKE_FUNDAMENTAL (10)
  48 #define G_TYPE_UINT64                   G_TYPE_MAKE_FUNDAMENTAL (11)
  49 #define G_TYPE_ENUM                     G_TYPE_MAKE_FUNDAMENTAL (12)
  50 #define G_TYPE_FLAGS                    G_TYPE_MAKE_FUNDAMENTAL (13)
  51 #define G_TYPE_FLOAT                    G_TYPE_MAKE_FUNDAMENTAL (14)
  52 #define G_TYPE_DOUBLE                   G_TYPE_MAKE_FUNDAMENTAL (15)
  53 #define G_TYPE_STRING                   G_TYPE_MAKE_FUNDAMENTAL (16)
  54 #define G_TYPE_POINTER                  G_TYPE_MAKE_FUNDAMENTAL (17)
  55 #define G_TYPE_BOXED                    G_TYPE_MAKE_FUNDAMENTAL (18)


  59 #define GTK_TYPE_BORDER                 ((*fp_gtk_border_get_type)())
  60 
  61 #define G_TYPE_FUNDAMENTAL_SHIFT        (2)
  62 #define G_TYPE_MAKE_FUNDAMENTAL(x)      ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
  63 #define MIN(a, b)  (((a) < (b)) ? (a) : (b))
  64 
  65 #define CONV_BUFFER_SIZE 128
  66 
  67 #define NO_SYMBOL_EXCEPTION 1
  68 
  69 /* SynthConstants */
  70 const gint ENABLED    = 1 << 0;
  71 const gint MOUSE_OVER = 1 << 1;
  72 const gint PRESSED    = 1 << 2;
  73 const gint DISABLED   = 1 << 3;
  74 const gint FOCUSED    = 1 << 8;
  75 const gint SELECTED   = 1 << 9;
  76 const gint DEFAULT    = 1 << 10;
  77 
  78 static void *gtk2_libhandle = NULL;
  79 static void *gthread_libhandle = NULL;
  80 static jmp_buf j;
  81 
  82 /* Widgets */
  83 static GtkWidget *gtk2_widget = NULL;
  84 static GtkWidget *gtk2_window = NULL;
  85 static GtkFixed  *gtk2_fixed  = NULL;
  86 
  87 /* Paint system */
  88 static GdkPixmap *gtk2_white_pixmap = NULL;
  89 static GdkPixmap *gtk2_black_pixmap = NULL;
  90 static GdkPixbuf *gtk2_white_pixbuf = NULL;
  91 static GdkPixbuf *gtk2_black_pixbuf = NULL;
  92 static int gtk2_pixbuf_width = 0;
  93 static int gtk2_pixbuf_height = 0;
  94 
  95 /* Static buffer for conversion from java.lang.String to UTF-8 */
  96 static char convertionBuffer[CONV_BUFFER_SIZE];
  97 
  98 static gboolean new_combo = TRUE;
  99 const char ENV_PREFIX[] = "GTK_MODULES=";


 135     _GTK_TOOLBAR_TYPE,
 136     _GTK_TOOLTIP_TYPE,
 137     _GTK_TREE_VIEW_TYPE,
 138     _GTK_VIEWPORT_TYPE,
 139     _GTK_VPANED_TYPE,
 140     _GTK_VPROGRESS_BAR_TYPE,
 141     _GTK_VSCALE_TYPE,
 142     _GTK_VSCROLLBAR_TYPE,
 143     _GTK_VSEPARATOR_TYPE,
 144     _GTK_WINDOW_TYPE,
 145     _GTK_DIALOG_TYPE,
 146     _GTK_WIDGET_TYPE_SIZE
 147 };
 148 
 149 
 150 static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE];
 151 
 152 /*************************
 153  * Glib function pointers
 154  *************************/

 155 
 156 static gboolean (*fp_g_main_context_iteration)(GMainContext *context,
 157                                              gboolean may_block);
 158 
 159 static GValue*      (*fp_g_value_init)(GValue *value, GType g_type);
 160 static gboolean     (*fp_g_type_is_a)(GType type, GType is_a_type);
 161 static gboolean     (*fp_g_value_get_boolean)(const GValue *value);
 162 static gchar        (*fp_g_value_get_char)(const GValue *value);
 163 static guchar       (*fp_g_value_get_uchar)(const GValue *value);
 164 static gint         (*fp_g_value_get_int)(const GValue *value);
 165 static guint        (*fp_g_value_get_uint)(const GValue *value);
 166 static glong        (*fp_g_value_get_long)(const GValue *value);
 167 static gulong       (*fp_g_value_get_ulong)(const GValue *value);
 168 static gint64       (*fp_g_value_get_int64)(const GValue *value);
 169 static guint64      (*fp_g_value_get_uint64)(const GValue *value);
 170 static gfloat       (*fp_g_value_get_float)(const GValue *value);
 171 static gdouble      (*fp_g_value_get_double)(const GValue *value);
 172 static const gchar* (*fp_g_value_get_string)(const GValue *value);
 173 static gint         (*fp_g_value_get_enum)(const GValue *value);
 174 static guint        (*fp_g_value_get_flags)(const GValue *value);


 188 /************************
 189  * GDK function pointers
 190  ************************/
 191 static GdkPixmap *(*fp_gdk_pixmap_new)(GdkDrawable *drawable,
 192         gint width, gint height, gint depth);
 193 static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*);
 194 static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32);
 195 static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean,
 196         gint, gint, gint, gint);
 197 static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace,
 198         gboolean has_alpha, int bits_per_sample, int width, int height);
 199 static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest,
 200         GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y,
 201         int dest_x, int dest_y, int width, int height);
 202 static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable,
 203         gint* width, gint* height);
 204 
 205 /************************
 206  * Gtk function pointers
 207  ************************/



 208 static gboolean (*fp_gtk_init_check)(int* argc, char** argv);
 209 
 210 /* Painting */
 211 static void (*fp_gtk_paint_hline)(GtkStyle* style, GdkWindow* window,
 212         GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,
 213         const gchar* detail, gint x1, gint x2, gint y);
 214 static void (*fp_gtk_paint_vline)(GtkStyle* style, GdkWindow* window,
 215         GtkStateType state_type, GdkRectangle* area, GtkWidget* widget,
 216         const gchar* detail, gint y1, gint y2, gint x);
 217 static void (*fp_gtk_paint_shadow)(GtkStyle* style, GdkWindow* window,
 218         GtkStateType state_type, GtkShadowType shadow_type,
 219         GdkRectangle* area, GtkWidget* widget, const gchar* detail,
 220         gint x, gint y, gint width, gint height);
 221 static void (*fp_gtk_paint_arrow)(GtkStyle* style, GdkWindow* window,
 222         GtkStateType state_type, GtkShadowType shadow_type,
 223         GdkRectangle* area, GtkWidget* widget, const gchar* detail,
 224         GtkArrowType arrow_type, gboolean fill, gint x, gint y,
 225         gint width, gint height);
 226 static void (*fp_gtk_paint_diamond)(GtkStyle* style, GdkWindow* window,
 227         GtkStateType state_type, GtkShadowType shadow_type,


 311 static GtkWidget* (*fp_gtk_toolbar_new)();
 312 static GtkWidget* (*fp_gtk_tree_view_new)();
 313 static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment,
 314         GtkAdjustment *vadjustment);
 315 static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type);
 316 static GtkWidget* (*fp_gtk_dialog_new)();
 317 static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment,
 318         gdouble climb_rate, guint digits);
 319 static GtkWidget* (*fp_gtk_frame_new)(const gchar *label);
 320 
 321 /* Other widget operations */
 322 static GtkObject* (*fp_gtk_adjustment_new)(gdouble value,
 323         gdouble lower, gdouble upper, gdouble step_increment,
 324         gdouble page_increment, gdouble page_size);
 325 static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget);
 326 static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell,
 327         GtkWidget *child);
 328 static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item,
 329         GtkWidget *submenu);
 330 static void (*fp_gtk_widget_realize)(GtkWidget *widget);

 331 static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget,
 332         const gchar *stock_id, GtkIconSize size, const gchar *detail);
 333 static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name);
 334 static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent);
 335 static void (*fp_gtk_widget_set_direction)(GtkWidget *widget,
 336         GtkTextDirection direction);
 337 static void (*fp_gtk_widget_style_get)(GtkWidget *widget,
 338         const gchar *first_property_name, ...);
 339 static void (*fp_gtk_widget_class_install_style_property)(
 340         GtkWidgetClass* class, GParamSpec *pspec);
 341 static GParamSpec* (*fp_gtk_widget_class_find_style_property)(
 342         GtkWidgetClass* class, const gchar* property_name);
 343 static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget,
 344         const gchar* property_name, GValue* value);
 345 static char* (*fp_pango_font_description_to_string)(
 346         const PangoFontDescription* fd);
 347 static GtkSettings* (*fp_gtk_settings_get_default)();
 348 static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget);
 349 static GType        (*fp_gtk_border_get_type)();
 350 static void (*fp_gtk_arrow_set)(GtkWidget* arrow,


 368 
 369     (*env)->GetStringUTFRegion(env, val, 0, length, convertionBuffer);
 370     return convertionBuffer;
 371 }
 372 
 373 /* This is a workaround for the bug:
 374  * http://sourceware.org/bugzilla/show_bug.cgi?id=1814
 375  * (dlsym/dlopen clears dlerror state)
 376  * This bug is specific to Linux, but there is no harm in
 377  * applying this workaround on Solaris as well.
 378  */
 379 static void* dl_symbol(const char* name)
 380 {
 381     void* result = dlsym(gtk2_libhandle, name);
 382     if (!result)
 383         longjmp(j, NO_SYMBOL_EXCEPTION);
 384 
 385     return result;
 386 }
 387 
 388 static void* dl_symbol_gthread(const char* name)
 389 {
 390     void* result = dlsym(gthread_libhandle, name);
 391     if (!result)
 392         longjmp(j, NO_SYMBOL_EXCEPTION);
 393 
 394     return result;
 395 }
 396 
 397 gboolean gtk2_check_version()
 398 {
 399     if (gtk2_libhandle != NULL) {
 400         /* We've already successfully opened the GTK libs, so return true. */
 401         return TRUE;
 402     } else {
 403         void *lib = NULL;
 404         gboolean result = FALSE;
 405 
 406         lib = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL);
 407         if (lib == NULL) {
 408             return FALSE;
 409         }
 410 
 411         fp_gtk_check_version = dlsym(lib, "gtk_check_version");
 412         /* Check for GTK 2.2+ */
 413         if (!fp_gtk_check_version(2, 2, 0)) {
 414             result = TRUE;
 415         }
 416 
 417         dlclose(lib);
 418 
 419         return result;
 420     }
 421 }
 422 
 423 /**
 424  * Functions for sun_awt_X11_GtkFileDialogPeer.c
 425  */
 426 void gtk2_file_chooser_load()
 427 {
 428     fp_gtk_file_chooser_get_filename = dl_symbol(
 429             "gtk_file_chooser_get_filename");
 430     fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new");
 431     fp_gtk_file_chooser_set_current_folder = dl_symbol(
 432             "gtk_file_chooser_set_current_folder");
 433     fp_gtk_file_chooser_set_filename = dl_symbol(
 434             "gtk_file_chooser_set_filename");
 435     fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom");
 436     fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");
 437     fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");
 438     fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");
 439     fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(
 440             "gtk_file_chooser_set_do_overwrite_confirmation");
 441     fp_gtk_file_chooser_set_select_multiple = dl_symbol(
 442             "gtk_file_chooser_set_select_multiple");
 443     fp_gtk_file_chooser_get_current_folder = dl_symbol(
 444             "gtk_file_chooser_get_current_folder");
 445     fp_gtk_file_chooser_get_filenames = dl_symbol(
 446             "gtk_file_chooser_get_filenames");
 447     fp_gtk_g_slist_length = dl_symbol("g_slist_length");
 448 }
 449 
 450 gboolean gtk2_load()
 451 {
 452     gboolean result;
 453     int i;
 454     int (*handler)();
 455     int (*io_handler)();
 456     char *gtk_modules_env;
 457 
 458     gtk2_libhandle = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL);
 459     gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL);
 460 
 461     if (gtk2_libhandle == NULL || gthread_libhandle == NULL)
 462         return FALSE;
 463 
 464     if (setjmp(j) == 0)
 465     {
 466         fp_gtk_check_version = dl_symbol("gtk_check_version");
 467         /* Check for GTK 2.2+ */
 468         if (fp_gtk_check_version(2, 2, 0)) {
 469             longjmp(j, NO_SYMBOL_EXCEPTION);
 470         }
 471 
 472         /* GLib */
 473         fp_g_free = dl_symbol("g_free");
 474         fp_g_object_unref = dl_symbol("g_object_unref");
 475 
 476         fp_g_main_context_iteration =
 477             dl_symbol("g_main_context_iteration");
 478 
 479         fp_g_value_init = dl_symbol("g_value_init");
 480         fp_g_type_is_a = dl_symbol("g_type_is_a");
 481 


 615             dl_symbol("gtk_widget_style_get");
 616         fp_gtk_widget_class_install_style_property =
 617             dl_symbol("gtk_widget_class_install_style_property");
 618         fp_gtk_widget_class_find_style_property =
 619             dl_symbol("gtk_widget_class_find_style_property");
 620         fp_gtk_widget_style_get_property =
 621             dl_symbol("gtk_widget_style_get_property");
 622         fp_pango_font_description_to_string =
 623             dl_symbol("pango_font_description_to_string");
 624         fp_gtk_settings_get_default =
 625             dl_symbol("gtk_settings_get_default");
 626         fp_gtk_widget_get_settings =
 627             dl_symbol("gtk_widget_get_settings");
 628         fp_gtk_border_get_type =  dl_symbol("gtk_border_get_type");
 629         fp_gtk_arrow_set = dl_symbol("gtk_arrow_set");
 630         fp_gtk_widget_size_request =
 631             dl_symbol("gtk_widget_size_request");
 632         fp_gtk_range_get_adjustment =
 633             dl_symbol("gtk_range_get_adjustment");
 634 
 635         fp_gtk_widget_hide = dl_symbol("gtk_widget_hide");
 636         fp_gtk_main_quit = dl_symbol("gtk_main_quit");
 637         fp_g_signal_connect_data = dl_symbol("g_signal_connect_data");
 638         fp_gtk_widget_show = dl_symbol("gtk_widget_show");
 639         fp_gtk_main = dl_symbol("gtk_main");
 640 
 641         /**
 642          * GLib thread system
 643          */
 644         fp_g_thread_get_initialized = dl_symbol_gthread(
 645                 "g_thread_get_initialized");
 646         fp_g_thread_init = dl_symbol_gthread("g_thread_init");
 647         fp_gdk_threads_init = dl_symbol("gdk_threads_init");
 648         fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");
 649         fp_gdk_threads_leave = dl_symbol("gdk_threads_leave");
 650 
 651         /**
 652          * Functions for sun_awt_X11_GtkFileDialogPeer.c
 653          */
 654         if (fp_gtk_check_version(2, 4, 0) == NULL) {
 655             // The current GtkFileChooser is available from GTK+ 2.4
 656             gtk2_file_chooser_load();
 657         }
 658 
 659         /* Some functions may be missing in pre-2.4 GTK.
 660            We handle them specially here.
 661          */
 662         fp_gtk_combo_box_new = dlsym(gtk2_libhandle, "gtk_combo_box_new");
 663         if (fp_gtk_combo_box_new == NULL) {
 664             fp_gtk_combo_box_new = dl_symbol("gtk_combo_new");
 665         }
 666 
 667         fp_gtk_combo_box_entry_new =
 668             dlsym(gtk2_libhandle, "gtk_combo_box_entry_new");
 669         if (fp_gtk_combo_box_entry_new == NULL) {
 670             fp_gtk_combo_box_entry_new = dl_symbol("gtk_combo_new");
 671             new_combo = FALSE;
 672         }
 673 
 674         fp_gtk_separator_tool_item_new =
 675             dlsym(gtk2_libhandle, "gtk_separator_tool_item_new");
 676         if (fp_gtk_separator_tool_item_new == NULL) {
 677             fp_gtk_separator_tool_item_new =
 678                 dl_symbol("gtk_vseparator_new");
 679         }
 680     }
 681     /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION
 682      * Otherwise we can check the return value of setjmp method.
 683      */
 684     else
 685     {
 686         dlclose(gtk2_libhandle);
 687         gtk2_libhandle = NULL;
 688 
 689         dlclose(gthread_libhandle);
 690         gthread_libhandle = NULL;
 691         
 692         return FALSE;
 693     }
 694 
 695     /*
 696      * Strip the AT-SPI GTK_MODULEs if present
 697      */
 698     gtk_modules_env = getenv ("GTK_MODULES");
 699 
 700     if (gtk_modules_env && strstr (gtk_modules_env, "atk-bridge") ||
 701         gtk_modules_env && strstr (gtk_modules_env, "gail"))
 702     {
 703         /* the new env will be smaller than the old one */
 704         gchar *s, *new_env = malloc (sizeof(ENV_PREFIX)+strlen (gtk_modules_env));
 705 
 706         if (new_env != NULL )
 707         {
 708             /* careful, strtok modifies its args */
 709             gchar *tmp_env = strdup (gtk_modules_env);
 710             strcpy(new_env, ENV_PREFIX);
 711 


 724                 {
 725                     free (tmp_env);
 726                     tmp_env = NULL; /* next call to strtok arg1==NULL */
 727                 }
 728             }
 729             putenv (new_env);
 730             free (new_env);
 731         }
 732     }
 733 
 734     /*
 735      * GTK should be initialized with gtk_init_check() before use.
 736      *
 737      * gtk_init_check installs its own error handlers. It is critical that
 738      * we preserve error handler set from AWT. Otherwise we'll crash on
 739      * BadMatch errors which we would normally ignore. The IO error handler
 740      * is preserved here, too, just for consistency.
 741     */
 742     handler = XSetErrorHandler(NULL);
 743     io_handler = XSetIOErrorHandler(NULL);
 744 
 745     if (fp_gtk_check_version(2, 2, 0) == NULL) {
 746         // Init the thread system to use GLib in a thread-safe mode
 747         if (!fp_g_thread_get_initialized()) {
 748             fp_g_thread_init(NULL);
 749 
 750             //According the GTK documentation, gdk_threads_init() should be
 751             //called before gtk_init() or gtk_init_check()
 752             fp_gdk_threads_init();
 753         }
 754     }
 755     result = (*fp_gtk_init_check)(NULL, NULL);
 756 
 757     XSetErrorHandler(handler);
 758     XSetIOErrorHandler(io_handler);
 759 
 760     /* Initialize widget array. */
 761     for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)
 762     {
 763         gtk2_widgets[i] = NULL;
 764     }
 765 
 766     return result;
 767 }
 768 
 769 int gtk2_unload()
 770 {
 771     int i;
 772     char *gtk2_error;
 773 
 774     if (!gtk2_libhandle)


 779         (*fp_g_object_unref)(gtk2_white_pixmap);
 780         (*fp_g_object_unref)(gtk2_black_pixmap);
 781         (*fp_g_object_unref)(gtk2_white_pixbuf);
 782         (*fp_g_object_unref)(gtk2_black_pixbuf);
 783         gtk2_white_pixmap = gtk2_black_pixmap =
 784             gtk2_white_pixbuf = gtk2_black_pixbuf = NULL;
 785     }
 786     gtk2_pixbuf_width = 0;
 787     gtk2_pixbuf_height = 0;
 788 
 789     if (gtk2_window != NULL) {
 790         /* Destroying toplevel widget will destroy all contained widgets */
 791         (*fp_gtk_widget_destroy)(gtk2_window);
 792 
 793         /* Unset some static data so they get reinitialized on next load */
 794         gtk2_window = NULL;
 795     }
 796 
 797     dlerror();
 798     dlclose(gtk2_libhandle);
 799     dlclose(gthread_libhandle);
 800     if ((gtk2_error = dlerror()) != NULL)
 801     {
 802         return FALSE;
 803     }
 804     return TRUE;
 805 }
 806 
 807 /* Dispatch all pending events from the GTK event loop.
 808  * This is needed to catch theme change and update widgets' style.
 809  */
 810 void flush_gtk_event_loop()
 811 {
 812     while( (*fp_g_main_context_iteration)(NULL, FALSE));
 813 }
 814 
 815 /*
 816  * Initialize components of containment hierarchy. This creates a GtkFixed
 817  * inside a GtkWindow. All widgets get realized.
 818  */
 819 static void init_containers()