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("g_thread_get_initialized");
645 fp_g_thread_init = dl_symbol_gthread("g_thread_init");
646 fp_gdk_threads_init = dl_symbol("gdk_threads_init");
647 fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");
648 fp_gdk_threads_leave = dl_symbol("gdk_threads_leave");
649
650 /**
651 * Functions for sun_awt_X11_GtkFileDialogPeer.c
652 */
653 if (fp_gtk_check_version(2, 4, 0) == NULL) {
654 // The current GtkFileChooser is available from GTK+ 2.4
655 gtk2_file_chooser_load();
656 }
657
658 /* Some functions may be missing in pre-2.4 GTK.
659 We handle them specially here.
660 */
661 fp_gtk_combo_box_new = dlsym(gtk2_libhandle, "gtk_combo_box_new");
662 if (fp_gtk_combo_box_new == NULL) {
663 fp_gtk_combo_box_new = dl_symbol("gtk_combo_new");
664 }
665
666 fp_gtk_combo_box_entry_new =
667 dlsym(gtk2_libhandle, "gtk_combo_box_entry_new");
668 if (fp_gtk_combo_box_entry_new == NULL) {
669 fp_gtk_combo_box_entry_new = dl_symbol("gtk_combo_new");
670 new_combo = FALSE;
671 }
672
673 fp_gtk_separator_tool_item_new =
674 dlsym(gtk2_libhandle, "gtk_separator_tool_item_new");
675 if (fp_gtk_separator_tool_item_new == NULL) {
676 fp_gtk_separator_tool_item_new =
677 dl_symbol("gtk_vseparator_new");
678 }
679 }
680 /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION
681 * Otherwise we can check the return value of setjmp method.
682 */
683 else
684 {
685 dlclose(gtk2_libhandle);
686 gtk2_libhandle = NULL;
687
688 dlclose(gthread_libhandle);
689 gthread_libhandle = NULL;
690
691 return FALSE;
692 }
693
694 /*
695 * Strip the AT-SPI GTK_MODULEs if present
696 */
697 gtk_modules_env = getenv ("GTK_MODULES");
698
699 if (gtk_modules_env && strstr (gtk_modules_env, "atk-bridge") ||
700 gtk_modules_env && strstr (gtk_modules_env, "gail"))
701 {
702 /* the new env will be smaller than the old one */
703 gchar *s, *new_env = malloc (sizeof(ENV_PREFIX)+strlen (gtk_modules_env));
704
705 if (new_env != NULL )
706 {
707 /* careful, strtok modifies its args */
708 gchar *tmp_env = strdup (gtk_modules_env);
709 strcpy(new_env, ENV_PREFIX);
710
723 {
724 free (tmp_env);
725 tmp_env = NULL; /* next call to strtok arg1==NULL */
726 }
727 }
728 putenv (new_env);
729 free (new_env);
730 }
731 }
732
733 /*
734 * GTK should be initialized with gtk_init_check() before use.
735 *
736 * gtk_init_check installs its own error handlers. It is critical that
737 * we preserve error handler set from AWT. Otherwise we'll crash on
738 * BadMatch errors which we would normally ignore. The IO error handler
739 * is preserved here, too, just for consistency.
740 */
741 handler = XSetErrorHandler(NULL);
742 io_handler = XSetIOErrorHandler(NULL);
743
744 if (fp_gtk_check_version(2, 2, 0) == NULL)
745 {
746 // Init the thread system to use GLib in a thread-safe mode
747 if (!fp_g_thread_get_initialized())
748 {
749 fp_g_thread_init(NULL);
750
751 //According the GTK documentation, gdk_threads_init() should be
752 //called before gtk_init() or gtk_init_check()
753 fp_gdk_threads_init();
754 }
755 }
756 result = (*fp_gtk_init_check)(NULL, NULL);
757
758 XSetErrorHandler(handler);
759 XSetIOErrorHandler(io_handler);
760
761 /* Initialize widget array. */
762 for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)
763 {
764 gtk2_widgets[i] = NULL;
765 }
766
767 return result;
768 }
769
770 int gtk2_unload()
771 {
772 int i;
773 char *gtk2_error;
774
775 if (!gtk2_libhandle)
780 (*fp_g_object_unref)(gtk2_white_pixmap);
781 (*fp_g_object_unref)(gtk2_black_pixmap);
782 (*fp_g_object_unref)(gtk2_white_pixbuf);
783 (*fp_g_object_unref)(gtk2_black_pixbuf);
784 gtk2_white_pixmap = gtk2_black_pixmap =
785 gtk2_white_pixbuf = gtk2_black_pixbuf = NULL;
786 }
787 gtk2_pixbuf_width = 0;
788 gtk2_pixbuf_height = 0;
789
790 if (gtk2_window != NULL) {
791 /* Destroying toplevel widget will destroy all contained widgets */
792 (*fp_gtk_widget_destroy)(gtk2_window);
793
794 /* Unset some static data so they get reinitialized on next load */
795 gtk2_window = NULL;
796 }
797
798 dlerror();
799 dlclose(gtk2_libhandle);
800 dlclose(gthread_libhandle);
801 if ((gtk2_error = dlerror()) != NULL)
802 {
803 return FALSE;
804 }
805 return TRUE;
806 }
807
808 /* Dispatch all pending events from the GTK event loop.
809 * This is needed to catch theme change and update widgets' style.
810 */
811 void flush_gtk_event_loop()
812 {
813 while( (*fp_g_main_context_iteration)(NULL, FALSE));
814 }
815
816 /*
817 * Initialize components of containment hierarchy. This creates a GtkFixed
818 * inside a GtkWindow. All widgets get realized.
819 */
820 static void init_containers()
|