1 /*
2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 #include <dlfcn.h>
26 #include <setjmp.h>
27 #include <X11/Xlib.h>
28 #include <limits.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include "gtk2_interface.h"
32 #include "java_awt_Transparency.h"
33 #include "jvm_md.h"
34 #include "sizecalc.h"
35 #include <jni_util.h>
36 #include "awt.h"
37
38 #define GTK2_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0")
39 #define GTK2_LIB JNI_LIB_NAME("gtk-x11-2.0")
40 #define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0")
41 #define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0")
42
43 #define G_TYPE_INVALID G_TYPE_MAKE_FUNDAMENTAL (0)
44 #define G_TYPE_NONE G_TYPE_MAKE_FUNDAMENTAL (1)
45 #define G_TYPE_INTERFACE G_TYPE_MAKE_FUNDAMENTAL (2)
46 #define G_TYPE_CHAR G_TYPE_MAKE_FUNDAMENTAL (3)
47 #define G_TYPE_UCHAR G_TYPE_MAKE_FUNDAMENTAL (4)
48 #define G_TYPE_BOOLEAN G_TYPE_MAKE_FUNDAMENTAL (5)
49 #define G_TYPE_INT G_TYPE_MAKE_FUNDAMENTAL (6)
50 #define G_TYPE_UINT G_TYPE_MAKE_FUNDAMENTAL (7)
51 #define G_TYPE_LONG G_TYPE_MAKE_FUNDAMENTAL (8)
52 #define G_TYPE_ULONG G_TYPE_MAKE_FUNDAMENTAL (9)
53 #define G_TYPE_INT64 G_TYPE_MAKE_FUNDAMENTAL (10)
54 #define G_TYPE_UINT64 G_TYPE_MAKE_FUNDAMENTAL (11)
55 #define G_TYPE_ENUM G_TYPE_MAKE_FUNDAMENTAL (12)
56 #define G_TYPE_FLAGS G_TYPE_MAKE_FUNDAMENTAL (13)
57 #define G_TYPE_FLOAT G_TYPE_MAKE_FUNDAMENTAL (14)
58 #define G_TYPE_DOUBLE G_TYPE_MAKE_FUNDAMENTAL (15)
59 #define G_TYPE_STRING G_TYPE_MAKE_FUNDAMENTAL (16)
60 #define G_TYPE_POINTER G_TYPE_MAKE_FUNDAMENTAL (17)
61 #define G_TYPE_BOXED G_TYPE_MAKE_FUNDAMENTAL (18)
62 #define G_TYPE_PARAM G_TYPE_MAKE_FUNDAMENTAL (19)
63 #define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20)
64
65 #define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)())
66
67 #define G_TYPE_FUNDAMENTAL_SHIFT (2)
68 #define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
69 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
70
71 #define CONV_BUFFER_SIZE 128
72
73 #define NO_SYMBOL_EXCEPTION 1
74
75 /* SynthConstants */
76 const gint ENABLED = 1 << 0;
77 const gint MOUSE_OVER = 1 << 1;
78 const gint PRESSED = 1 << 2;
79 const gint DISABLED = 1 << 3;
80 const gint FOCUSED = 1 << 8;
81 const gint SELECTED = 1 << 9;
82 const gint DEFAULT = 1 << 10;
83
84 static void *gtk2_libhandle = NULL;
85 static void *gthread_libhandle = NULL;
86
87 static jmp_buf j;
88
89 /* Widgets */
90 static GtkWidget *gtk2_widget = NULL;
91 static GtkWidget *gtk2_window = NULL;
92 static GtkFixed *gtk2_fixed = NULL;
93
94 /* Paint system */
95 static GdkPixmap *gtk2_white_pixmap = NULL;
96 static GdkPixmap *gtk2_black_pixmap = NULL;
97 static GdkPixbuf *gtk2_white_pixbuf = NULL;
98 static GdkPixbuf *gtk2_black_pixbuf = NULL;
99 static int gtk2_pixbuf_width = 0;
100 static int gtk2_pixbuf_height = 0;
101
102 /* Static buffer for conversion from java.lang.String to UTF-8 */
103 static char convertionBuffer[CONV_BUFFER_SIZE];
104
105 static gboolean new_combo = TRUE;
106 const char ENV_PREFIX[] = "GTK_MODULES=";
107
108 /*******************/
109 enum GtkWidgetType
110 {
111 _GTK_ARROW_TYPE,
112 _GTK_BUTTON_TYPE,
113 _GTK_CHECK_BUTTON_TYPE,
114 _GTK_CHECK_MENU_ITEM_TYPE,
115 _GTK_COLOR_SELECTION_DIALOG_TYPE,
116 _GTK_COMBO_BOX_TYPE,
117 _GTK_COMBO_BOX_ARROW_BUTTON_TYPE,
118 _GTK_COMBO_BOX_TEXT_FIELD_TYPE,
119 _GTK_CONTAINER_TYPE,
120 _GTK_ENTRY_TYPE,
121 _GTK_FRAME_TYPE,
122 _GTK_HANDLE_BOX_TYPE,
123 _GTK_HPANED_TYPE,
124 _GTK_HPROGRESS_BAR_TYPE,
125 _GTK_HSCALE_TYPE,
126 _GTK_HSCROLLBAR_TYPE,
127 _GTK_HSEPARATOR_TYPE,
128 _GTK_IMAGE_TYPE,
129 _GTK_MENU_TYPE,
130 _GTK_MENU_BAR_TYPE,
131 _GTK_MENU_ITEM_TYPE,
132 _GTK_NOTEBOOK_TYPE,
133 _GTK_LABEL_TYPE,
134 _GTK_RADIO_BUTTON_TYPE,
135 _GTK_RADIO_MENU_ITEM_TYPE,
136 _GTK_SCROLLED_WINDOW_TYPE,
137 _GTK_SEPARATOR_MENU_ITEM_TYPE,
138 _GTK_SEPARATOR_TOOL_ITEM_TYPE,
139 _GTK_SPIN_BUTTON_TYPE,
140 _GTK_TEXT_VIEW_TYPE,
141 _GTK_TOGGLE_BUTTON_TYPE,
142 _GTK_TOOLBAR_TYPE,
143 _GTK_TOOLTIP_TYPE,
144 _GTK_TREE_VIEW_TYPE,
145 _GTK_VIEWPORT_TYPE,
146 _GTK_VPANED_TYPE,
147 _GTK_VPROGRESS_BAR_TYPE,
148 _GTK_VSCALE_TYPE,
149 _GTK_VSCROLLBAR_TYPE,
150 _GTK_VSEPARATOR_TYPE,
151 _GTK_WINDOW_TYPE,
152 _GTK_DIALOG_TYPE,
153 _GTK_WIDGET_TYPE_SIZE
154 };
155
156
157 static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE];
158
159 /*************************
160 * Glib function pointers
161 *************************/
162
163 static gboolean (*fp_g_main_context_iteration)(GMainContext *context,
164 gboolean may_block);
165
166 static GValue* (*fp_g_value_init)(GValue *value, GType g_type);
167 static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type);
168 static gboolean (*fp_g_value_get_boolean)(const GValue *value);
169 static gchar (*fp_g_value_get_char)(const GValue *value);
170 static guchar (*fp_g_value_get_uchar)(const GValue *value);
171 static gint (*fp_g_value_get_int)(const GValue *value);
172 static guint (*fp_g_value_get_uint)(const GValue *value);
173 static glong (*fp_g_value_get_long)(const GValue *value);
174 static gulong (*fp_g_value_get_ulong)(const GValue *value);
175 static gint64 (*fp_g_value_get_int64)(const GValue *value);
342 const gchar *first_property_name, ...);
343 static void (*fp_gtk_widget_class_install_style_property)(
344 GtkWidgetClass* class, GParamSpec *pspec);
345 static GParamSpec* (*fp_gtk_widget_class_find_style_property)(
346 GtkWidgetClass* class, const gchar* property_name);
347 static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget,
348 const gchar* property_name, GValue* value);
349 static char* (*fp_pango_font_description_to_string)(
350 const PangoFontDescription* fd);
351 static GtkSettings* (*fp_gtk_settings_get_default)();
352 static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget);
353 static GType (*fp_gtk_border_get_type)();
354 static void (*fp_gtk_arrow_set)(GtkWidget* arrow,
355 GtkArrowType arrow_type,
356 GtkShadowType shadow_type);
357 static void (*fp_gtk_widget_size_request)(GtkWidget *widget,
358 GtkRequisition *requisition);
359 static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range);
360
361 /* Method bodies */
362 const char *getStrFor(JNIEnv *env, jstring val)
363 {
364 int length = (*env)->GetStringLength(env, val);
365 if (length > CONV_BUFFER_SIZE-1)
366 {
367 length = CONV_BUFFER_SIZE-1;
368 #ifdef DEBUG
369 fprintf(stderr, "Note: Detail is too long: %d chars\n", length);
370 #endif /* DEBUG */
371 }
372
373 (*env)->GetStringUTFRegion(env, val, 0, length, convertionBuffer);
374 return convertionBuffer;
375 }
376
377 static void throw_exception(JNIEnv *env, const char* name, const char* message)
378 {
379 jclass class = (*env)->FindClass(env, name);
380
381 if (class != NULL)
382 (*env)->ThrowNew(env, class, message);
383
384 (*env)->DeleteLocalRef(env, class);
385 }
386
387 /* This is a workaround for the bug:
388 * http://sourceware.org/bugzilla/show_bug.cgi?id=1814
389 * (dlsym/dlopen clears dlerror state)
390 * This bug is specific to Linux, but there is no harm in
391 * applying this workaround on Solaris as well.
392 */
393 static void* dl_symbol(const char* name)
394 {
395 void* result = dlsym(gtk2_libhandle, name);
396 if (!result)
397 longjmp(j, NO_SYMBOL_EXCEPTION);
398
399 return result;
400 }
401
402 static void* dl_symbol_gthread(const char* name)
403 {
404 void* result = dlsym(gthread_libhandle, name);
405 if (!result)
406 longjmp(j, NO_SYMBOL_EXCEPTION);
407
408 return result;
409 }
410
411 gboolean gtk2_check_version()
412 {
413 if (gtk2_libhandle != NULL) {
414 /* We've already successfully opened the GTK libs, so return true. */
415 return TRUE;
416 } else {
417 void *lib = NULL;
418 gboolean result = FALSE;
419
420 lib = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
421 if (lib == NULL) {
422 lib = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL);
423 if (lib == NULL) {
424 return FALSE;
425 }
426 }
427
428 fp_gtk_check_version = dlsym(lib, "gtk_check_version");
429 /* Check for GTK 2.2+ */
430 if (!fp_gtk_check_version(2, 2, 0)) {
431 result = TRUE;
432 }
433
434 // 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065
435 // dlclose(lib);
436
437 return result;
438 }
439 }
440
441 #define ADD_SUPPORTED_ACTION(actionStr) \
442 do { \
443 jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, "Ljava/awt/Desktop$Action;"); \
444 if (!(*env)->ExceptionCheck(env)) { \
445 jobject action = (*env)->GetStaticObjectField(env, cls_action, fld_action); \
446 (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, action); \
447 } else { \
448 (*env)->ExceptionClear(env); \
449 } \
450 } while(0);
451
452
453 void update_supported_actions(JNIEnv *env) {
454 GVfs * (*fp_g_vfs_get_default) (void);
455 const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);
456 const gchar * const * schemes = NULL;
457
458 jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action");
459 CHECK_NULL(cls_action);
460 jclass cls_xDesktopPeer = (*env)->FindClass(env, "sun/awt/X11/XDesktopPeer");
461 CHECK_NULL(cls_xDesktopPeer);
462 jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, cls_xDesktopPeer, "supportedActions", "Ljava/util/List;");
463 CHECK_NULL(fld_supportedActions);
464 jobject supportedActions = (*env)->GetStaticObjectField(env, cls_xDesktopPeer, fld_supportedActions);
465
466 jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList");
467 CHECK_NULL(cls_arrayList);
468 jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", "(Ljava/lang/Object;)Z");
469 CHECK_NULL(mid_arrayListAdd);
470 jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, "clear", "()V");
471 CHECK_NULL(mid_arrayListClear);
472
473 (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear);
496 int i = 0;
497 while (schemes[i]) {
498 if (strcmp(schemes[i], "http") == 0) {
499 ADD_SUPPORTED_ACTION("BROWSE");
500 ADD_SUPPORTED_ACTION("MAIL");
501 break;
502 }
503 i++;
504 }
505 }
506 } else {
507 #ifdef DEBUG
508 fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n");
509 #endif /* DEBUG */
510 }
511
512 }
513 /**
514 * Functions for awt_Desktop.c
515 */
516 gboolean gtk2_show_uri_load(JNIEnv *env) {
517 gboolean success = FALSE;
518 dlerror();
519 const char *gtk_version = fp_gtk_check_version(2, 14, 0);
520 if (gtk_version != NULL) {
521 // The gtk_show_uri is available from GTK+ 2.14
522 #ifdef DEBUG
523 fprintf (stderr, "The version of GTK is %s. "
524 "The gtk_show_uri function is supported "
525 "since GTK+ 2.14.\n", gtk_version);
526 #endif /* DEBUG */
527 } else {
528 // Loading symbols only if the GTK version is 2.14 and higher
529 fp_gtk_show_uri = dl_symbol("gtk_show_uri");
530 const char *dlsym_error = dlerror();
531 if (dlsym_error) {
532 #ifdef DEBUG
533 fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error);
534 #endif /* DEBUG */
535 } else if (fp_gtk_show_uri == NULL) {
536 #ifdef DEBUG
537 fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");
538 #endif /* DEBUG */
539 } else {
540 update_supported_actions(env);
541 success = TRUE;
542 }
543 }
544 return success;
545 }
546
547 /**
548 * Functions for sun_awt_X11_GtkFileDialogPeer.c
549 */
550 void gtk2_file_chooser_load()
551 {
552 fp_gtk_file_chooser_get_filename = dl_symbol(
553 "gtk_file_chooser_get_filename");
554 fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new");
555 fp_gtk_file_chooser_set_current_folder = dl_symbol(
556 "gtk_file_chooser_set_current_folder");
557 fp_gtk_file_chooser_set_filename = dl_symbol(
558 "gtk_file_chooser_set_filename");
559 fp_gtk_file_chooser_set_current_name = dl_symbol(
560 "gtk_file_chooser_set_current_name");
561 fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom");
562 fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");
563 fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");
564 fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");
565 if (fp_gtk_check_version(2, 8, 0) == NULL) {
566 fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(
567 "gtk_file_chooser_set_do_overwrite_confirmation");
568 }
569 fp_gtk_file_chooser_set_select_multiple = dl_symbol(
570 "gtk_file_chooser_set_select_multiple");
571 fp_gtk_file_chooser_get_current_folder = dl_symbol(
572 "gtk_file_chooser_get_current_folder");
573 fp_gtk_file_chooser_get_filenames = dl_symbol(
574 "gtk_file_chooser_get_filenames");
575 fp_gtk_g_slist_length = dl_symbol("g_slist_length");
576 fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid");
577 }
578
579 gboolean gtk2_load(JNIEnv *env)
580 {
581 gboolean result;
582 int i;
583 int (*handler)();
584 int (*io_handler)();
585 char *gtk_modules_env;
586
587 gtk2_libhandle = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
588 if (gtk2_libhandle == NULL) {
589 gtk2_libhandle = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL);
590 if (gtk2_libhandle == NULL)
591 return FALSE;
592 }
593
594 gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
595 if (gthread_libhandle == NULL) {
596 gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL);
597 if (gthread_libhandle == NULL)
598 return FALSE;
599 }
600
601 if (setjmp(j) == 0)
602 {
603 fp_gtk_check_version = dl_symbol("gtk_check_version");
604 /* Check for GTK 2.2+ */
605 if (fp_gtk_check_version(2, 2, 0)) {
606 longjmp(j, NO_SYMBOL_EXCEPTION);
607 }
608
609 /* GLib */
610 fp_glib_check_version = dlsym(gtk2_libhandle, "glib_check_version");
941 if (pendExcpn != NULL) {
942 (*env)->Throw(env, pendExcpn);
943 }
944 // check if any exception occured during mid_unlock call
945 if ((*env)->ExceptionCheck(env)) {
946 AWT_UNLOCK();
947 return FALSE;
948 }
949 }
950 result = (*fp_gtk_init_check)(NULL, NULL);
951
952 XSetErrorHandler(handler);
953 XSetIOErrorHandler(io_handler);
954 AWT_UNLOCK();
955
956 /* Initialize widget array. */
957 for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)
958 {
959 gtk2_widgets[i] = NULL;
960 }
961
962 return result;
963 }
964
965 int gtk2_unload()
966 {
967 int i;
968 char *gtk2_error;
969
970 if (!gtk2_libhandle)
971 return TRUE;
972
973 /* Release painting objects */
974 if (gtk2_white_pixmap != NULL) {
975 (*fp_g_object_unref)(gtk2_white_pixmap);
976 (*fp_g_object_unref)(gtk2_black_pixmap);
977 (*fp_g_object_unref)(gtk2_white_pixbuf);
978 (*fp_g_object_unref)(gtk2_black_pixbuf);
979 gtk2_white_pixmap = gtk2_black_pixmap =
980 gtk2_white_pixbuf = gtk2_black_pixbuf = NULL;
981 }
982 gtk2_pixbuf_width = 0;
986 /* Destroying toplevel widget will destroy all contained widgets */
987 (*fp_gtk_widget_destroy)(gtk2_window);
988
989 /* Unset some static data so they get reinitialized on next load */
990 gtk2_window = NULL;
991 }
992
993 dlerror();
994 dlclose(gtk2_libhandle);
995 dlclose(gthread_libhandle);
996 if ((gtk2_error = dlerror()) != NULL)
997 {
998 return FALSE;
999 }
1000 return TRUE;
1001 }
1002
1003 /* Dispatch all pending events from the GTK event loop.
1004 * This is needed to catch theme change and update widgets' style.
1005 */
1006 void flush_gtk_event_loop()
1007 {
1008 while( (*fp_g_main_context_iteration)(NULL, FALSE));
1009 }
1010
1011 /*
1012 * Initialize components of containment hierarchy. This creates a GtkFixed
1013 * inside a GtkWindow. All widgets get realized.
1014 */
1015 static void init_containers()
1016 {
1017 if (gtk2_window == NULL)
1018 {
1019 gtk2_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);
1020 gtk2_fixed = (GtkFixed *)(*fp_gtk_fixed_new)();
1021 (*fp_gtk_container_add)((GtkContainer*)gtk2_window,
1022 (GtkWidget *)gtk2_fixed);
1023 (*fp_gtk_widget_realize)(gtk2_window);
1024 (*fp_gtk_widget_realize)((GtkWidget *)gtk2_fixed);
1025 }
1026 }
1035 * work around this:
1036 * 1) Subclass GdkPixmap and cache translucent objects on client side. This
1037 * requires us to implement parts of X server drawing logic on client side.
1038 * Many X requests can potentially be "translucent"; e.g. XDrawLine with
1039 * fill=tile and a translucent tile is a "translucent" operation, whereas
1040 * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some
1041 * do) intermix transparent and opaque operations which makes caching even
1042 * more problematic.
1043 * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support
1044 * for it (as of version 2.6). Also even in JDS 3 Xorg does not support
1045 * these visuals by default, which makes optimizing for them pointless.
1046 * We can consider doing this at a later point when ARGB visuals become more
1047 * popular.
1048 * 3') GTK has plans to use Cairo as its graphical backend (presumably in
1049 * 2.8), and Cairo supports alpha. With it we could also get rid of the
1050 * unnecessary round trip to server and do all the drawing on client side.
1051 * 4) For now we draw to two different pixmaps and restore alpha channel by
1052 * comparing results. This can be optimized by using subclassed pixmap and
1053 * doing the second drawing only if necessary.
1054 */
1055 void gtk2_init_painting(JNIEnv *env, gint width, gint height)
1056 {
1057 GdkGC *gc;
1058 GdkPixbuf *white, *black;
1059
1060 init_containers();
1061
1062 if (gtk2_pixbuf_width < width || gtk2_pixbuf_height < height)
1063 {
1064 white = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
1065 black = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
1066
1067 if (white == NULL || black == NULL)
1068 {
1069 snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height);
1070 throw_exception(env, "java/lang/RuntimeException", convertionBuffer);
1071 fp_gdk_threads_leave();
1072 return;
1073 }
1074
1075 if (gtk2_white_pixmap != NULL) {
1095 (*fp_gdk_rgb_gc_set_foreground)(gc, 0xffffff);
1096 (*fp_gdk_draw_rectangle)(gtk2_white_pixmap, gc, TRUE, 0, 0, width, height);
1097 (*fp_g_object_unref)(gc);
1098
1099 gc = (*fp_gdk_gc_new)(gtk2_black_pixmap);
1100 (*fp_gdk_rgb_gc_set_foreground)(gc, 0x000000);
1101 (*fp_gdk_draw_rectangle)(gtk2_black_pixmap, gc, TRUE, 0, 0, width, height);
1102 (*fp_g_object_unref)(gc);
1103 }
1104
1105 /*
1106 * Restore image from white and black pixmaps and copy it into destination
1107 * buffer. This method compares two pixbufs taken from white and black
1108 * pixmaps and decodes color and alpha components. Pixbufs are RGB without
1109 * alpha, destination buffer is ABGR.
1110 *
1111 * The return value is the transparency type of the resulting image, either
1112 * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and
1113 * java_awt_Transparency_TRANSLUCENT.
1114 */
1115 gint gtk2_copy_image(gint *dst, gint width, gint height)
1116 {
1117 gint i, j, r, g, b;
1118 guchar *white, *black;
1119 gint stride, padding;
1120 gboolean is_opaque = TRUE;
1121 gboolean is_bitmask = TRUE;
1122
1123 (*fp_gdk_pixbuf_get_from_drawable)(gtk2_white_pixbuf, gtk2_white_pixmap,
1124 NULL, 0, 0, 0, 0, width, height);
1125 (*fp_gdk_pixbuf_get_from_drawable)(gtk2_black_pixbuf, gtk2_black_pixmap,
1126 NULL, 0, 0, 0, 0, width, height);
1127
1128 white = (*fp_gdk_pixbuf_get_pixels)(gtk2_white_pixbuf);
1129 black = (*fp_gdk_pixbuf_get_pixels)(gtk2_black_pixbuf);
1130 stride = (*fp_gdk_pixbuf_get_rowstride)(gtk2_black_pixbuf);
1131 padding = stride - width * 4;
1132
1133 for (i = 0; i < height; i++) {
1134 for (j = 0; j < width; j++) {
1135 int r1 = *white++;
1757 h = size.height - ((GtkMisc*)gtk2_widget)->ypad * 2;
1758 w = h = MIN(MIN(w, h), MIN(width,height)) * 0.7;
1759 break;
1760
1761 default:
1762 w = width;
1763 h = height;
1764 break;
1765 }
1766 x += (width - w) / 2;
1767 y += (height - h) / 2;
1768
1769 (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1770 shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,
1771 x, y, w, h);
1772 (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1773 shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,
1774 x, y, w, h);
1775 }
1776
1777 void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,
1778 GtkShadowType shadow_type, const gchar *detail,
1779 gint x, gint y, gint width, gint height,
1780 gint synth_state, GtkTextDirection dir)
1781 {
1782 gtk2_widget = gtk2_get_widget(widget_type);
1783
1784 /*
1785 * The clearlooks engine sometimes looks at the widget's state field
1786 * instead of just the state_type variable that we pass in, so to account
1787 * for those cases we set the widget's state field accordingly. The
1788 * flags field is similarly important for things like focus/default state.
1789 */
1790 gtk2_widget->state = state_type;
1791
1792 if (widget_type == HSLIDER_TRACK) {
1793 /*
1794 * For horizontal JSliders with right-to-left orientation, we need
1795 * to set the "inverted" flag to match the native GTK behavior where
1796 * the foreground highlight is on the right side of the slider thumb.
1797 * This is needed especially for the ubuntulooks engine, which looks
1927 gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);
1928 }
1929
1930 void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type,
1931 GtkShadowType shadow_type, const gchar *detail,
1932 gint x, gint y, gint width, gint height,
1933 GtkPositionType gap_side, gint gap_x, gint gap_width)
1934 {
1935 /* Clearlooks needs a real clip area to paint the gap properly */
1936 GdkRectangle area = { x, y, width, height };
1937
1938 gtk2_widget = gtk2_get_widget(widget_type);
1939 (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1940 shadow_type, &area, gtk2_widget, detail,
1941 x, y, width, height, gap_side, gap_x, gap_width);
1942 (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1943 shadow_type, &area, gtk2_widget, detail,
1944 x, y, width, height, gap_side, gap_x, gap_width);
1945 }
1946
1947 void gtk2_paint_check(WidgetType widget_type, gint synth_state,
1948 const gchar *detail, gint x, gint y, gint width, gint height)
1949 {
1950 GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);
1951 GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);
1952
1953 gtk2_widget = gtk2_get_widget(widget_type);
1954 init_toggle_widget(widget_type, synth_state);
1955
1956 (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1957 shadow_type, NULL, gtk2_widget, detail,
1958 x, y, width, height);
1959 (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1960 shadow_type, NULL, gtk2_widget, detail,
1961 x, y, width, height);
1962 }
1963
1964 void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,
1965 GtkShadowType shadow_type, const gchar *detail,
1966 gint x, gint y, gint width, gint height)
1967 {
1968 gtk2_widget = gtk2_get_widget(widget_type);
1969 (*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1970 shadow_type, NULL, gtk2_widget, detail,
1971 x, y, width, height);
1972 (*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1973 shadow_type, NULL, gtk2_widget, detail,
1974 x, y, width, height);
1975 }
1976
1977 void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,
1978 const gchar *detail, gint x, gint y, gint width, gint height,
1979 GtkExpanderStyle expander_style)
1980 {
1981 gtk2_widget = gtk2_get_widget(widget_type);
1982 (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_white_pixmap,
1983 state_type, NULL, gtk2_widget, detail,
1984 x + width / 2, y + height / 2, expander_style);
1985 (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_black_pixmap,
1986 state_type, NULL, gtk2_widget, detail,
1987 x + width / 2, y + height / 2, expander_style);
1988 }
1989
1990 void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,
1991 GtkShadowType shadow_type, const gchar *detail,
1992 gint x, gint y, gint width, gint height, GtkPositionType gap_side)
1993 {
1994 gtk2_widget = gtk2_get_widget(widget_type);
1995 (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_white_pixmap,
1996 state_type, shadow_type, NULL, gtk2_widget, detail,
1997 x, y, width, height, gap_side);
1998 (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_black_pixmap,
1999 state_type, shadow_type, NULL, gtk2_widget, detail,
2000 x, y, width, height, gap_side);
2001 }
2002
2003 void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
2004 GtkShadowType shadow_type, const gchar *detail,
2005 gint x, gint y, gint width, gint height, gboolean has_focus)
2006 {
2007 gtk2_widget = gtk2_get_widget(widget_type);
2008
2009 if (has_focus)
2010 ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;
2011 else
2012 ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;
2013
2014 (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_white_pixmap,
2015 state_type, shadow_type, NULL, gtk2_widget, detail,
2016 x, y, width, height);
2017 (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_black_pixmap,
2018 state_type, shadow_type, NULL, gtk2_widget, detail,
2019 x, y, width, height);
2020 }
2021
2022 void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,
2023 const char *detail, gint x, gint y, gint width, gint height)
2024 {
2025 gtk2_widget = gtk2_get_widget(widget_type);
2026 (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2027 NULL, gtk2_widget, detail, x, y, width, height);
2028 (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2029 NULL, gtk2_widget, detail, x, y, width, height);
2030 }
2031
2032 void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,
2033 GtkShadowType shadow_type, const gchar *detail,
2034 gint x, gint y, gint width, gint height, GtkOrientation orientation)
2035 {
2036 gtk2_widget = gtk2_get_widget(widget_type);
2037 (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2038 shadow_type, NULL, gtk2_widget, detail,
2039 x, y, width, height, orientation);
2040 (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2041 shadow_type, NULL, gtk2_widget, detail,
2042 x, y, width, height, orientation);
2043 }
2044
2045 void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,
2046 const gchar *detail, gint x, gint y, gint width, gint height)
2047 {
2048 gtk2_widget = gtk2_get_widget(widget_type);
2049 (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2050 NULL, gtk2_widget, detail, x, x + width, y);
2051 (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2052 NULL, gtk2_widget, detail, x, x + width, y);
2053 }
2054
2055 void gtk2_paint_option(WidgetType widget_type, gint synth_state,
2056 const gchar *detail, gint x, gint y, gint width, gint height)
2057 {
2058 GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);
2059 GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);
2060
2061 gtk2_widget = gtk2_get_widget(widget_type);
2062 init_toggle_widget(widget_type, synth_state);
2063
2064 (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2065 shadow_type, NULL, gtk2_widget, detail,
2066 x, y, width, height);
2067 (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2068 shadow_type, NULL, gtk2_widget, detail,
2069 x, y, width, height);
2070 }
2071
2072 void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,
2073 GtkShadowType shadow_type, const gchar *detail,
2074 gint x, gint y, gint width, gint height,
2075 gint synth_state, GtkTextDirection dir)
2076 {
2077 gtk2_widget = gtk2_get_widget(widget_type);
2078
2079 /*
2080 * The clearlooks engine sometimes looks at the widget's state field
2081 * instead of just the state_type variable that we pass in, so to account
2082 * for those cases we set the widget's state field accordingly. The
2083 * flags field is similarly important for things like focus state.
2084 */
2085 gtk2_widget->state = state_type;
2086
2087 /*
2088 * Some engines (e.g. clearlooks) will paint the shadow of certain
2089 * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the
2090 * the text direction.
2091 */
2092 gtk2_set_direction(gtk2_widget, dir);
2102 } else {
2103 ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;
2104 }
2105 break;
2106 default:
2107 break;
2108 }
2109
2110 (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2111 shadow_type, NULL, gtk2_widget, detail, x, y, width, height);
2112 (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2113 shadow_type, NULL, gtk2_widget, detail, x, y, width, height);
2114
2115 /*
2116 * Reset the text direction to the default value so that we don't
2117 * accidentally affect other operations and widgets.
2118 */
2119 gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);
2120 }
2121
2122 void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,
2123 GtkShadowType shadow_type, const gchar *detail,
2124 gint x, gint y, gint width, gint height, GtkOrientation orientation)
2125 {
2126 gtk2_widget = gtk2_get_widget(widget_type);
2127 (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2128 shadow_type, NULL, gtk2_widget, detail,
2129 x, y, width, height, orientation);
2130 (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2131 shadow_type, NULL, gtk2_widget, detail,
2132 x, y, width, height, orientation);
2133 }
2134
2135 void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,
2136 const gchar *detail, gint x, gint y, gint width, gint height)
2137 {
2138 gtk2_widget = gtk2_get_widget(widget_type);
2139 (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2140 NULL, gtk2_widget, detail, y, y + height, x);
2141 (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2142 NULL, gtk2_widget, detail, y, y + height, x);
2143 }
2144
2145 void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,
2146 gint x, gint y, gint width, gint height)
2147 {
2148 gtk2_widget = gtk2_get_widget(widget_type);
2149 (*fp_gtk_style_apply_default_background)(gtk2_widget->style,
2150 gtk2_white_pixmap, TRUE, state_type, NULL, x, y, width, height);
2151 (*fp_gtk_style_apply_default_background)(gtk2_widget->style,
2152 gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height);
2153 }
2154
2155 GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,
2156 GtkIconSize size, GtkTextDirection direction, const char *detail)
2157 {
2158 init_containers();
2159 gtk2_widget = gtk2_get_widget((widget_type < 0) ? IMAGE : widget_type);
2160 gtk2_widget->state = GTK_STATE_NORMAL;
2161 (*fp_gtk_widget_set_direction)(gtk2_widget, direction);
2162 return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail);
2163 }
2164
2165 /*************************************************/
2166 gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type)
2167 {
2168 init_containers();
2169
2170 gtk2_widget = gtk2_get_widget(widget_type);
2171 GtkStyle* style = gtk2_widget->style;
2172 return style->xthickness;
2173 }
2174
2175 gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type)
2176 {
2177 init_containers();
2178
2179 gtk2_widget = gtk2_get_widget(widget_type);
2180 GtkStyle* style = gtk2_widget->style;
2181 return style->ythickness;
2182 }
2183
2184 /*************************************************/
2185 guint8 recode_color(guint16 channel)
2186 {
2187 return (guint8)(channel>>8);
2188 }
2189
2190 gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,
2191 GtkStateType state_type, ColorType color_type)
2192 {
2193 gint result = 0;
2194 GdkColor *color = NULL;
2195
2196 init_containers();
2197
2198 gtk2_widget = gtk2_get_widget(widget_type);
2199 GtkStyle* style = gtk2_widget->style;
2200
2201 switch (color_type)
2202 {
2203 case FOREGROUND:
2204 color = &(style->fg[state_type]);
2205 break;
2206 case BACKGROUND:
2207 color = &(style->bg[state_type]);
2208 break;
2209 case TEXT_FOREGROUND:
2210 color = &(style->text[state_type]);
2222 color = &(style->mid[state_type]);
2223 break;
2224 case FOCUS:
2225 case BLACK:
2226 color = &(style->black);
2227 break;
2228 case WHITE:
2229 color = &(style->white);
2230 break;
2231 }
2232
2233 if (color)
2234 result = recode_color(color->red) << 16 |
2235 recode_color(color->green) << 8 |
2236 recode_color(color->blue);
2237
2238 return result;
2239 }
2240
2241 /*************************************************/
2242 jobject create_Boolean(JNIEnv *env, jboolean boolean_value);
2243 jobject create_Integer(JNIEnv *env, jint int_value);
2244 jobject create_Long(JNIEnv *env, jlong long_value);
2245 jobject create_Float(JNIEnv *env, jfloat float_value);
2246 jobject create_Double(JNIEnv *env, jdouble double_value);
2247 jobject create_Character(JNIEnv *env, jchar char_value);
2248 jobject create_Insets(JNIEnv *env, GtkBorder *border);
2249
2250 jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring jkey)
2251 {
2252 init_containers();
2253
2254 const char* key = getStrFor(env, jkey);
2255 gtk2_widget = gtk2_get_widget(widget_type);
2256
2257 GValue value;
2258 value.g_type = 0;
2259
2260 GParamSpec* param = (*fp_gtk_widget_class_find_style_property)(
2261 ((GTypeInstance*)gtk2_widget)->g_class, key);
2262 if( param )
2263 {
2264 (*fp_g_value_init)( &value, param->value_type );
2265 (*fp_gtk_widget_style_get_property)(gtk2_widget, key, &value);
2266
2267 if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN ))
2268 {
2269 gboolean val = (*fp_g_value_get_boolean)(&value);
2270 return create_Boolean(env, (jboolean)val);
2271 }
2272 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR ))
2273 {
2274 gchar val = (*fp_g_value_get_char)(&value);
2355 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED ))
2356 {
2357 gpointer* val = (*fp_g_value_get_boxed)(&value);
2358 printf( "Boxed: %p\n", val );
2359 }
2360 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER ))
2361 {
2362 gpointer* val = (*fp_g_value_get_pointer)(&value);
2363 printf( "Pointer: %p\n", val );
2364 }
2365 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT ))
2366 {
2367 GObject* val = (GObject*)(*fp_g_value_get_object)(&value);
2368 printf( "Object: %p\n", val );
2369 }*/
2370 }
2371
2372 return NULL;
2373 }
2374
2375 void gtk2_set_range_value(WidgetType widget_type, jdouble value,
2376 jdouble min, jdouble max, jdouble visible)
2377 {
2378 GtkAdjustment *adj;
2379
2380 gtk2_widget = gtk2_get_widget(widget_type);
2381
2382 adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk2_widget);
2383 adj->value = (gdouble)value;
2384 adj->lower = (gdouble)min;
2385 adj->upper = (gdouble)max;
2386 adj->page_size = (gdouble)visible;
2387 }
2388
2389 /*************************************************/
2390 jobject create_Object(JNIEnv *env, jmethodID *cid,
2391 const char* class_name,
2392 const char* signature,
2393 jvalue* value)
2394 {
2395 jclass class;
2396 jobject result;
2397
2398 class = (*env)->FindClass(env, class_name);
2399 if( class == NULL )
2400 return NULL; /* can't find/load the class, exception thrown */
2401
2402 if( *cid == NULL)
2403 {
2404 *cid = (*env)->GetMethodID(env, class, "<init>", signature);
2405 if( *cid == NULL )
2406 {
2407 (*env)->DeleteLocalRef(env, class);
2408 return NULL; /* can't find/get the method, exception thrown */
2409 }
2410 }
2473 value.c = char_value;
2474
2475 return create_Object(env, &cid, "java/lang/Character", "(C)V", &value);
2476 }
2477
2478
2479 jobject create_Insets(JNIEnv *env, GtkBorder *border)
2480 {
2481 static jmethodID cid = NULL;
2482 jvalue values[4];
2483
2484 values[0].i = border->top;
2485 values[1].i = border->left;
2486 values[2].i = border->bottom;
2487 values[3].i = border->right;
2488
2489 return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values);
2490 }
2491
2492 /*********************************************/
2493 jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type)
2494 {
2495 init_containers();
2496
2497 gtk2_widget = gtk2_get_widget(widget_type);
2498 jstring result = NULL;
2499 GtkStyle* style = gtk2_widget->style;
2500
2501 if (style && style->font_desc)
2502 {
2503 gchar* val = (*fp_pango_font_description_to_string)(style->font_desc);
2504 result = (*env)->NewStringUTF(env, val);
2505 (*fp_g_free)( val );
2506 }
2507
2508 return result;
2509 }
2510
2511 /***********************************************/
2512 jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
2513 {
2514 jobject result = NULL;
2515 gchar* strval = NULL;
2516
2517 (*fp_g_object_get)(settings, key, &strval, NULL);
2518 result = (*env)->NewStringUTF(env, strval);
2519 (*fp_g_free)(strval);
2520
2521 return result;
2522 }
2523
2524 jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
2525 {
2526 gint intval = NULL;
2527 (*fp_g_object_get)(settings, key, &intval, NULL);
2528 return create_Integer(env, intval);
2529 }
2530
2531 jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
2532 {
2533 gint intval = NULL;
2534 (*fp_g_object_get)(settings, key, &intval, NULL);
2535 return create_Boolean(env, intval);
2536 }
2537
2538 jobject gtk2_get_setting(JNIEnv *env, Setting property)
2539 {
2540 GtkSettings* settings = (*fp_gtk_settings_get_default)();
2541
2542 switch (property)
2543 {
2544 case GTK_FONT_NAME:
2545 return get_string_property(env, settings, "gtk-font-name");
2546 case GTK_ICON_SIZES:
2547 return get_string_property(env, settings, "gtk-icon-sizes");
2548 case GTK_CURSOR_BLINK:
2549 return get_boolean_property(env, settings, "gtk-cursor-blink");
2550 case GTK_CURSOR_BLINK_TIME:
2551 return get_integer_property(env, settings, "gtk-cursor-blink-time");
2552 }
2553
2554 return NULL;
2555 }
|
1 /*
2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 #include <dlfcn.h>
26 #include <setjmp.h>
27 #include <X11/Xlib.h>
28 #include <limits.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include "gtk2_interface.h"
32 #include "java_awt_Transparency.h"
33 #include "jvm_md.h"
34 #include "sizecalc.h"
35 #include <jni_util.h>
36 #include "awt.h"
37
38 #define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0")
39 #define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0")
40
41 #define GTK_TYPE_BORDER ((*fp_gtk_border_get_type)())
42
43 #define G_TYPE_FUNDAMENTAL_SHIFT (2)
44 #define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
45
46 #define CONV_BUFFER_SIZE 128
47
48 #define NO_SYMBOL_EXCEPTION 1
49
50 static void *gtk2_libhandle = NULL;
51 static void *gthread_libhandle = NULL;
52
53 static jmp_buf j;
54
55 /* Widgets */
56 static GtkWidget *gtk2_widget = NULL;
57 static GtkWidget *gtk2_window = NULL;
58 static GtkFixed *gtk2_fixed = NULL;
59
60 /* Paint system */
61 static GdkPixmap *gtk2_white_pixmap = NULL;
62 static GdkPixmap *gtk2_black_pixmap = NULL;
63 static GdkPixbuf *gtk2_white_pixbuf = NULL;
64 static GdkPixbuf *gtk2_black_pixbuf = NULL;
65 static int gtk2_pixbuf_width = 0;
66 static int gtk2_pixbuf_height = 0;
67
68 /* Static buffer for conversion from java.lang.String to UTF-8 */
69 static char convertionBuffer[CONV_BUFFER_SIZE];
70
71 static gboolean new_combo = TRUE;
72 const char ENV_PREFIX[] = "GTK_MODULES=";
73
74
75 static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE];
76
77 /*************************
78 * Glib function pointers
79 *************************/
80
81 static gboolean (*fp_g_main_context_iteration)(GMainContext *context,
82 gboolean may_block);
83
84 static GValue* (*fp_g_value_init)(GValue *value, GType g_type);
85 static gboolean (*fp_g_type_is_a)(GType type, GType is_a_type);
86 static gboolean (*fp_g_value_get_boolean)(const GValue *value);
87 static gchar (*fp_g_value_get_char)(const GValue *value);
88 static guchar (*fp_g_value_get_uchar)(const GValue *value);
89 static gint (*fp_g_value_get_int)(const GValue *value);
90 static guint (*fp_g_value_get_uint)(const GValue *value);
91 static glong (*fp_g_value_get_long)(const GValue *value);
92 static gulong (*fp_g_value_get_ulong)(const GValue *value);
93 static gint64 (*fp_g_value_get_int64)(const GValue *value);
260 const gchar *first_property_name, ...);
261 static void (*fp_gtk_widget_class_install_style_property)(
262 GtkWidgetClass* class, GParamSpec *pspec);
263 static GParamSpec* (*fp_gtk_widget_class_find_style_property)(
264 GtkWidgetClass* class, const gchar* property_name);
265 static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget,
266 const gchar* property_name, GValue* value);
267 static char* (*fp_pango_font_description_to_string)(
268 const PangoFontDescription* fd);
269 static GtkSettings* (*fp_gtk_settings_get_default)();
270 static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget);
271 static GType (*fp_gtk_border_get_type)();
272 static void (*fp_gtk_arrow_set)(GtkWidget* arrow,
273 GtkArrowType arrow_type,
274 GtkShadowType shadow_type);
275 static void (*fp_gtk_widget_size_request)(GtkWidget *widget,
276 GtkRequisition *requisition);
277 static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range);
278
279 /* Method bodies */
280
281 static void throw_exception(JNIEnv *env, const char* name, const char* message)
282 {
283 jclass class = (*env)->FindClass(env, name);
284
285 if (class != NULL)
286 (*env)->ThrowNew(env, class, message);
287
288 (*env)->DeleteLocalRef(env, class);
289 }
290
291 /* This is a workaround for the bug:
292 * http://sourceware.org/bugzilla/show_bug.cgi?id=1814
293 * (dlsym/dlopen clears dlerror state)
294 * This bug is specific to Linux, but there is no harm in
295 * applying this workaround on Solaris as well.
296 */
297 static void* dl_symbol(const char* name)
298 {
299 void* result = dlsym(gtk2_libhandle, name);
300 if (!result)
301 longjmp(j, NO_SYMBOL_EXCEPTION);
302
303 return result;
304 }
305
306 static void* dl_symbol_gthread(const char* name)
307 {
308 void* result = dlsym(gthread_libhandle, name);
309 if (!result)
310 longjmp(j, NO_SYMBOL_EXCEPTION);
311
312 return result;
313 }
314
315 gboolean gtk2_check(const char* lib_name, int flags)
316 {
317 if (gtk2_libhandle != NULL) {
318 /* We've already successfully opened the GTK libs, so return true. */
319 return TRUE;
320 } else {
321 void *lib = NULL;
322
323 lib = dlopen(lib_name, flags);
324
325 if (lib == NULL) {
326 return FALSE;
327 }
328
329 if (flags & RTLD_NOLOAD) {
330 return TRUE;
331 }
332
333 fp_gtk_check_version = dlsym(lib, "gtk_check_version");
334 /* Check for GTK 2.2+ */
335 if (!fp_gtk_check_version(2, 2, 0)) {
336 return TRUE;
337 }
338
339 // 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065
340 // dlclose(lib);
341
342 return FALSE;
343 }
344 }
345
346 #define ADD_SUPPORTED_ACTION(actionStr) \
347 do { \
348 jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, "Ljava/awt/Desktop$Action;"); \
349 if (!(*env)->ExceptionCheck(env)) { \
350 jobject action = (*env)->GetStaticObjectField(env, cls_action, fld_action); \
351 (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd, action); \
352 } else { \
353 (*env)->ExceptionClear(env); \
354 } \
355 } while(0);
356
357
358 static void update_supported_actions(JNIEnv *env) {
359 GVfs * (*fp_g_vfs_get_default) (void);
360 const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);
361 const gchar * const * schemes = NULL;
362
363 jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action");
364 CHECK_NULL(cls_action);
365 jclass cls_xDesktopPeer = (*env)->FindClass(env, "sun/awt/X11/XDesktopPeer");
366 CHECK_NULL(cls_xDesktopPeer);
367 jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env, cls_xDesktopPeer, "supportedActions", "Ljava/util/List;");
368 CHECK_NULL(fld_supportedActions);
369 jobject supportedActions = (*env)->GetStaticObjectField(env, cls_xDesktopPeer, fld_supportedActions);
370
371 jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList");
372 CHECK_NULL(cls_arrayList);
373 jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add", "(Ljava/lang/Object;)Z");
374 CHECK_NULL(mid_arrayListAdd);
375 jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList, "clear", "()V");
376 CHECK_NULL(mid_arrayListClear);
377
378 (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear);
401 int i = 0;
402 while (schemes[i]) {
403 if (strcmp(schemes[i], "http") == 0) {
404 ADD_SUPPORTED_ACTION("BROWSE");
405 ADD_SUPPORTED_ACTION("MAIL");
406 break;
407 }
408 i++;
409 }
410 }
411 } else {
412 #ifdef DEBUG
413 fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n");
414 #endif /* DEBUG */
415 }
416
417 }
418 /**
419 * Functions for awt_Desktop.c
420 */
421 static gboolean gtk2_show_uri_load(JNIEnv *env) {
422 gboolean success = FALSE;
423 dlerror();
424 const char *gtk_version = fp_gtk_check_version(2, 14, 0);
425 if (gtk_version != NULL) {
426 // The gtk_show_uri is available from GTK+ 2.14
427 #ifdef DEBUG
428 fprintf (stderr, "The version of GTK is %s. "
429 "The gtk_show_uri function is supported "
430 "since GTK+ 2.14.\n", gtk_version);
431 #endif /* DEBUG */
432 } else {
433 // Loading symbols only if the GTK version is 2.14 and higher
434 fp_gtk_show_uri = dl_symbol("gtk_show_uri");
435 const char *dlsym_error = dlerror();
436 if (dlsym_error) {
437 #ifdef DEBUG
438 fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error);
439 #endif /* DEBUG */
440 } else if (fp_gtk_show_uri == NULL) {
441 #ifdef DEBUG
442 fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");
443 #endif /* DEBUG */
444 } else {
445 update_supported_actions(env);
446 success = TRUE;
447 }
448 }
449 return success;
450 }
451
452 /**
453 * Functions for sun_awt_X11_GtkFileDialogPeer.c
454 */
455 static void gtk2_file_chooser_load()
456 {
457 fp_gtk_file_chooser_get_filename = dl_symbol(
458 "gtk_file_chooser_get_filename");
459 fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new");
460 fp_gtk_file_chooser_set_current_folder = dl_symbol(
461 "gtk_file_chooser_set_current_folder");
462 fp_gtk_file_chooser_set_filename = dl_symbol(
463 "gtk_file_chooser_set_filename");
464 fp_gtk_file_chooser_set_current_name = dl_symbol(
465 "gtk_file_chooser_set_current_name");
466 fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom");
467 fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");
468 fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");
469 fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");
470 if (fp_gtk_check_version(2, 8, 0) == NULL) {
471 fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(
472 "gtk_file_chooser_set_do_overwrite_confirmation");
473 }
474 fp_gtk_file_chooser_set_select_multiple = dl_symbol(
475 "gtk_file_chooser_set_select_multiple");
476 fp_gtk_file_chooser_get_current_folder = dl_symbol(
477 "gtk_file_chooser_get_current_folder");
478 fp_gtk_file_chooser_get_filenames = dl_symbol(
479 "gtk_file_chooser_get_filenames");
480 fp_gtk_g_slist_length = dl_symbol("g_slist_length");
481 fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid");
482 }
483
484 GtkApi* gtk2_load(JNIEnv *env, const char* lib_name)
485 {
486 gboolean result;
487 int i;
488 int (*handler)();
489 int (*io_handler)();
490 char *gtk_modules_env;
491
492 gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);
493 if (gtk2_libhandle == NULL) {
494 return FALSE;
495 }
496
497 gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
498 if (gthread_libhandle == NULL) {
499 gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL);
500 if (gthread_libhandle == NULL)
501 return FALSE;
502 }
503
504 if (setjmp(j) == 0)
505 {
506 fp_gtk_check_version = dl_symbol("gtk_check_version");
507 /* Check for GTK 2.2+ */
508 if (fp_gtk_check_version(2, 2, 0)) {
509 longjmp(j, NO_SYMBOL_EXCEPTION);
510 }
511
512 /* GLib */
513 fp_glib_check_version = dlsym(gtk2_libhandle, "glib_check_version");
844 if (pendExcpn != NULL) {
845 (*env)->Throw(env, pendExcpn);
846 }
847 // check if any exception occured during mid_unlock call
848 if ((*env)->ExceptionCheck(env)) {
849 AWT_UNLOCK();
850 return FALSE;
851 }
852 }
853 result = (*fp_gtk_init_check)(NULL, NULL);
854
855 XSetErrorHandler(handler);
856 XSetIOErrorHandler(io_handler);
857 AWT_UNLOCK();
858
859 /* Initialize widget array. */
860 for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)
861 {
862 gtk2_widgets[i] = NULL;
863 }
864 if (result) {
865 GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi));
866 gtk2_init(gtk);
867 return gtk;
868 }
869 return NULL;
870 }
871
872 int gtk2_unload()
873 {
874 int i;
875 char *gtk2_error;
876
877 if (!gtk2_libhandle)
878 return TRUE;
879
880 /* Release painting objects */
881 if (gtk2_white_pixmap != NULL) {
882 (*fp_g_object_unref)(gtk2_white_pixmap);
883 (*fp_g_object_unref)(gtk2_black_pixmap);
884 (*fp_g_object_unref)(gtk2_white_pixbuf);
885 (*fp_g_object_unref)(gtk2_black_pixbuf);
886 gtk2_white_pixmap = gtk2_black_pixmap =
887 gtk2_white_pixbuf = gtk2_black_pixbuf = NULL;
888 }
889 gtk2_pixbuf_width = 0;
893 /* Destroying toplevel widget will destroy all contained widgets */
894 (*fp_gtk_widget_destroy)(gtk2_window);
895
896 /* Unset some static data so they get reinitialized on next load */
897 gtk2_window = NULL;
898 }
899
900 dlerror();
901 dlclose(gtk2_libhandle);
902 dlclose(gthread_libhandle);
903 if ((gtk2_error = dlerror()) != NULL)
904 {
905 return FALSE;
906 }
907 return TRUE;
908 }
909
910 /* Dispatch all pending events from the GTK event loop.
911 * This is needed to catch theme change and update widgets' style.
912 */
913 static void flush_gtk_event_loop()
914 {
915 while( (*fp_g_main_context_iteration)(NULL, FALSE));
916 }
917
918 /*
919 * Initialize components of containment hierarchy. This creates a GtkFixed
920 * inside a GtkWindow. All widgets get realized.
921 */
922 static void init_containers()
923 {
924 if (gtk2_window == NULL)
925 {
926 gtk2_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);
927 gtk2_fixed = (GtkFixed *)(*fp_gtk_fixed_new)();
928 (*fp_gtk_container_add)((GtkContainer*)gtk2_window,
929 (GtkWidget *)gtk2_fixed);
930 (*fp_gtk_widget_realize)(gtk2_window);
931 (*fp_gtk_widget_realize)((GtkWidget *)gtk2_fixed);
932 }
933 }
942 * work around this:
943 * 1) Subclass GdkPixmap and cache translucent objects on client side. This
944 * requires us to implement parts of X server drawing logic on client side.
945 * Many X requests can potentially be "translucent"; e.g. XDrawLine with
946 * fill=tile and a translucent tile is a "translucent" operation, whereas
947 * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some
948 * do) intermix transparent and opaque operations which makes caching even
949 * more problematic.
950 * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support
951 * for it (as of version 2.6). Also even in JDS 3 Xorg does not support
952 * these visuals by default, which makes optimizing for them pointless.
953 * We can consider doing this at a later point when ARGB visuals become more
954 * popular.
955 * 3') GTK has plans to use Cairo as its graphical backend (presumably in
956 * 2.8), and Cairo supports alpha. With it we could also get rid of the
957 * unnecessary round trip to server and do all the drawing on client side.
958 * 4) For now we draw to two different pixmaps and restore alpha channel by
959 * comparing results. This can be optimized by using subclassed pixmap and
960 * doing the second drawing only if necessary.
961 */
962 static void gtk2_init_painting(JNIEnv *env, gint width, gint height)
963 {
964 GdkGC *gc;
965 GdkPixbuf *white, *black;
966
967 init_containers();
968
969 if (gtk2_pixbuf_width < width || gtk2_pixbuf_height < height)
970 {
971 white = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
972 black = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
973
974 if (white == NULL || black == NULL)
975 {
976 snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height);
977 throw_exception(env, "java/lang/RuntimeException", convertionBuffer);
978 fp_gdk_threads_leave();
979 return;
980 }
981
982 if (gtk2_white_pixmap != NULL) {
1002 (*fp_gdk_rgb_gc_set_foreground)(gc, 0xffffff);
1003 (*fp_gdk_draw_rectangle)(gtk2_white_pixmap, gc, TRUE, 0, 0, width, height);
1004 (*fp_g_object_unref)(gc);
1005
1006 gc = (*fp_gdk_gc_new)(gtk2_black_pixmap);
1007 (*fp_gdk_rgb_gc_set_foreground)(gc, 0x000000);
1008 (*fp_gdk_draw_rectangle)(gtk2_black_pixmap, gc, TRUE, 0, 0, width, height);
1009 (*fp_g_object_unref)(gc);
1010 }
1011
1012 /*
1013 * Restore image from white and black pixmaps and copy it into destination
1014 * buffer. This method compares two pixbufs taken from white and black
1015 * pixmaps and decodes color and alpha components. Pixbufs are RGB without
1016 * alpha, destination buffer is ABGR.
1017 *
1018 * The return value is the transparency type of the resulting image, either
1019 * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and
1020 * java_awt_Transparency_TRANSLUCENT.
1021 */
1022 static gint gtk2_copy_image(gint *dst, gint width, gint height)
1023 {
1024 gint i, j, r, g, b;
1025 guchar *white, *black;
1026 gint stride, padding;
1027 gboolean is_opaque = TRUE;
1028 gboolean is_bitmask = TRUE;
1029
1030 (*fp_gdk_pixbuf_get_from_drawable)(gtk2_white_pixbuf, gtk2_white_pixmap,
1031 NULL, 0, 0, 0, 0, width, height);
1032 (*fp_gdk_pixbuf_get_from_drawable)(gtk2_black_pixbuf, gtk2_black_pixmap,
1033 NULL, 0, 0, 0, 0, width, height);
1034
1035 white = (*fp_gdk_pixbuf_get_pixels)(gtk2_white_pixbuf);
1036 black = (*fp_gdk_pixbuf_get_pixels)(gtk2_black_pixbuf);
1037 stride = (*fp_gdk_pixbuf_get_rowstride)(gtk2_black_pixbuf);
1038 padding = stride - width * 4;
1039
1040 for (i = 0; i < height; i++) {
1041 for (j = 0; j < width; j++) {
1042 int r1 = *white++;
1664 h = size.height - ((GtkMisc*)gtk2_widget)->ypad * 2;
1665 w = h = MIN(MIN(w, h), MIN(width,height)) * 0.7;
1666 break;
1667
1668 default:
1669 w = width;
1670 h = height;
1671 break;
1672 }
1673 x += (width - w) / 2;
1674 y += (height - h) / 2;
1675
1676 (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1677 shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,
1678 x, y, w, h);
1679 (*fp_gtk_paint_arrow)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1680 shadow_type, NULL, gtk2_widget, detail, arrow_type, fill,
1681 x, y, w, h);
1682 }
1683
1684 static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,
1685 GtkShadowType shadow_type, const gchar *detail,
1686 gint x, gint y, gint width, gint height,
1687 gint synth_state, GtkTextDirection dir)
1688 {
1689 gtk2_widget = gtk2_get_widget(widget_type);
1690
1691 /*
1692 * The clearlooks engine sometimes looks at the widget's state field
1693 * instead of just the state_type variable that we pass in, so to account
1694 * for those cases we set the widget's state field accordingly. The
1695 * flags field is similarly important for things like focus/default state.
1696 */
1697 gtk2_widget->state = state_type;
1698
1699 if (widget_type == HSLIDER_TRACK) {
1700 /*
1701 * For horizontal JSliders with right-to-left orientation, we need
1702 * to set the "inverted" flag to match the native GTK behavior where
1703 * the foreground highlight is on the right side of the slider thumb.
1704 * This is needed especially for the ubuntulooks engine, which looks
1834 gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);
1835 }
1836
1837 void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type,
1838 GtkShadowType shadow_type, const gchar *detail,
1839 gint x, gint y, gint width, gint height,
1840 GtkPositionType gap_side, gint gap_x, gint gap_width)
1841 {
1842 /* Clearlooks needs a real clip area to paint the gap properly */
1843 GdkRectangle area = { x, y, width, height };
1844
1845 gtk2_widget = gtk2_get_widget(widget_type);
1846 (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1847 shadow_type, &area, gtk2_widget, detail,
1848 x, y, width, height, gap_side, gap_x, gap_width);
1849 (*fp_gtk_paint_box_gap)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1850 shadow_type, &area, gtk2_widget, detail,
1851 x, y, width, height, gap_side, gap_x, gap_width);
1852 }
1853
1854 static void gtk2_paint_check(WidgetType widget_type, gint synth_state,
1855 const gchar *detail, gint x, gint y, gint width, gint height)
1856 {
1857 GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);
1858 GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);
1859
1860 gtk2_widget = gtk2_get_widget(widget_type);
1861 init_toggle_widget(widget_type, synth_state);
1862
1863 (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1864 shadow_type, NULL, gtk2_widget, detail,
1865 x, y, width, height);
1866 (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1867 shadow_type, NULL, gtk2_widget, detail,
1868 x, y, width, height);
1869 }
1870
1871 static void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,
1872 GtkShadowType shadow_type, const gchar *detail,
1873 gint x, gint y, gint width, gint height)
1874 {
1875 gtk2_widget = gtk2_get_widget(widget_type);
1876 (*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1877 shadow_type, NULL, gtk2_widget, detail,
1878 x, y, width, height);
1879 (*fp_gtk_paint_diamond)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1880 shadow_type, NULL, gtk2_widget, detail,
1881 x, y, width, height);
1882 }
1883
1884 static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,
1885 const gchar *detail, gint x, gint y, gint width, gint height,
1886 GtkExpanderStyle expander_style)
1887 {
1888 gtk2_widget = gtk2_get_widget(widget_type);
1889 (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_white_pixmap,
1890 state_type, NULL, gtk2_widget, detail,
1891 x + width / 2, y + height / 2, expander_style);
1892 (*fp_gtk_paint_expander)(gtk2_widget->style, gtk2_black_pixmap,
1893 state_type, NULL, gtk2_widget, detail,
1894 x + width / 2, y + height / 2, expander_style);
1895 }
1896
1897 static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,
1898 GtkShadowType shadow_type, const gchar *detail,
1899 gint x, gint y, gint width, gint height, GtkPositionType gap_side)
1900 {
1901 gtk2_widget = gtk2_get_widget(widget_type);
1902 (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_white_pixmap,
1903 state_type, shadow_type, NULL, gtk2_widget, detail,
1904 x, y, width, height, gap_side);
1905 (*fp_gtk_paint_extension)(gtk2_widget->style, gtk2_black_pixmap,
1906 state_type, shadow_type, NULL, gtk2_widget, detail,
1907 x, y, width, height, gap_side);
1908 }
1909
1910 static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
1911 GtkShadowType shadow_type, const gchar *detail,
1912 gint x, gint y, gint width, gint height, gboolean has_focus)
1913 {
1914 gtk2_widget = gtk2_get_widget(widget_type);
1915
1916 if (has_focus)
1917 ((GtkObject*)gtk2_widget)->flags |= GTK_HAS_FOCUS;
1918 else
1919 ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;
1920
1921 (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_white_pixmap,
1922 state_type, shadow_type, NULL, gtk2_widget, detail,
1923 x, y, width, height);
1924 (*fp_gtk_paint_flat_box)(gtk2_widget->style, gtk2_black_pixmap,
1925 state_type, shadow_type, NULL, gtk2_widget, detail,
1926 x, y, width, height);
1927 }
1928
1929 static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,
1930 const char *detail, gint x, gint y, gint width, gint height)
1931 {
1932 gtk2_widget = gtk2_get_widget(widget_type);
1933 (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1934 NULL, gtk2_widget, detail, x, y, width, height);
1935 (*fp_gtk_paint_focus)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1936 NULL, gtk2_widget, detail, x, y, width, height);
1937 }
1938
1939 static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,
1940 GtkShadowType shadow_type, const gchar *detail,
1941 gint x, gint y, gint width, gint height, GtkOrientation orientation)
1942 {
1943 gtk2_widget = gtk2_get_widget(widget_type);
1944 (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1945 shadow_type, NULL, gtk2_widget, detail,
1946 x, y, width, height, orientation);
1947 (*fp_gtk_paint_handle)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1948 shadow_type, NULL, gtk2_widget, detail,
1949 x, y, width, height, orientation);
1950 }
1951
1952 static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,
1953 const gchar *detail, gint x, gint y, gint width, gint height)
1954 {
1955 gtk2_widget = gtk2_get_widget(widget_type);
1956 (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1957 NULL, gtk2_widget, detail, x, x + width, y);
1958 (*fp_gtk_paint_hline)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1959 NULL, gtk2_widget, detail, x, x + width, y);
1960 }
1961
1962 static void gtk2_paint_option(WidgetType widget_type, gint synth_state,
1963 const gchar *detail, gint x, gint y, gint width, gint height)
1964 {
1965 GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);
1966 GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state);
1967
1968 gtk2_widget = gtk2_get_widget(widget_type);
1969 init_toggle_widget(widget_type, synth_state);
1970
1971 (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_white_pixmap, state_type,
1972 shadow_type, NULL, gtk2_widget, detail,
1973 x, y, width, height);
1974 (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_black_pixmap, state_type,
1975 shadow_type, NULL, gtk2_widget, detail,
1976 x, y, width, height);
1977 }
1978
1979 static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,
1980 GtkShadowType shadow_type, const gchar *detail,
1981 gint x, gint y, gint width, gint height,
1982 gint synth_state, GtkTextDirection dir)
1983 {
1984 gtk2_widget = gtk2_get_widget(widget_type);
1985
1986 /*
1987 * The clearlooks engine sometimes looks at the widget's state field
1988 * instead of just the state_type variable that we pass in, so to account
1989 * for those cases we set the widget's state field accordingly. The
1990 * flags field is similarly important for things like focus state.
1991 */
1992 gtk2_widget->state = state_type;
1993
1994 /*
1995 * Some engines (e.g. clearlooks) will paint the shadow of certain
1996 * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the
1997 * the text direction.
1998 */
1999 gtk2_set_direction(gtk2_widget, dir);
2009 } else {
2010 ((GtkObject*)gtk2_widget)->flags &= ~GTK_HAS_FOCUS;
2011 }
2012 break;
2013 default:
2014 break;
2015 }
2016
2017 (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2018 shadow_type, NULL, gtk2_widget, detail, x, y, width, height);
2019 (*fp_gtk_paint_shadow)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2020 shadow_type, NULL, gtk2_widget, detail, x, y, width, height);
2021
2022 /*
2023 * Reset the text direction to the default value so that we don't
2024 * accidentally affect other operations and widgets.
2025 */
2026 gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);
2027 }
2028
2029 static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,
2030 GtkShadowType shadow_type, const gchar *detail,
2031 gint x, gint y, gint width, gint height, GtkOrientation orientation,
2032 gboolean has_focus)
2033 {
2034 gtk2_widget = gtk2_get_widget(widget_type);
2035 (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2036 shadow_type, NULL, gtk2_widget, detail,
2037 x, y, width, height, orientation);
2038 (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2039 shadow_type, NULL, gtk2_widget, detail,
2040 x, y, width, height, orientation);
2041 }
2042
2043 static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,
2044 const gchar *detail, gint x, gint y, gint width, gint height)
2045 {
2046 gtk2_widget = gtk2_get_widget(widget_type);
2047 (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_white_pixmap, state_type,
2048 NULL, gtk2_widget, detail, y, y + height, x);
2049 (*fp_gtk_paint_vline)(gtk2_widget->style, gtk2_black_pixmap, state_type,
2050 NULL, gtk2_widget, detail, y, y + height, x);
2051 }
2052
2053 static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,
2054 gint x, gint y, gint width, gint height)
2055 {
2056 gtk2_widget = gtk2_get_widget(widget_type);
2057 (*fp_gtk_style_apply_default_background)(gtk2_widget->style,
2058 gtk2_white_pixmap, TRUE, state_type, NULL, x, y, width, height);
2059 (*fp_gtk_style_apply_default_background)(gtk2_widget->style,
2060 gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height);
2061 }
2062
2063 static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,
2064 GtkIconSize size, GtkTextDirection direction, const char *detail)
2065 {
2066 init_containers();
2067 gtk2_widget = gtk2_get_widget((widget_type < 0) ? IMAGE : widget_type);
2068 gtk2_widget->state = GTK_STATE_NORMAL;
2069 (*fp_gtk_widget_set_direction)(gtk2_widget, direction);
2070 return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail);
2071 }
2072
2073 static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf,
2074 jmethodID icon_upcall_method, jobject this) {
2075 if (!pixbuf) {
2076 return JNI_FALSE;
2077 }
2078 guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
2079 if (pixbuf_data) {
2080 int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
2081 int width = (*fp_gdk_pixbuf_get_width)(pixbuf);
2082 int height = (*fp_gdk_pixbuf_get_height)(pixbuf);
2083 int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);
2084 int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
2085 gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);
2086
2087 jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));
2088 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
2089
2090 (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),
2091 (jbyte *)pixbuf_data);
2092 (*fp_g_object_unref)(pixbuf);
2093
2094 /* Call the callback method to create the image on the Java side. */
2095 (*env)->CallVoidMethod(env, this, icon_upcall_method, data,
2096 width, height, row_stride, bps, channels, alpha);
2097 return JNI_TRUE;
2098 }
2099 return JNI_FALSE;
2100 }
2101
2102 static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename,
2103 GError **error, jmethodID icon_upcall_method, jobject this) {
2104 GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error);
2105 return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
2106 }
2107
2108 static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type,
2109 const gchar *stock_id, GtkIconSize size,
2110 GtkTextDirection direction, const char *detail,
2111 jmethodID icon_upcall_method, jobject this) {
2112 GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size,
2113 direction, detail);
2114 return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
2115 }
2116
2117 /*************************************************/
2118 static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type)
2119 {
2120 init_containers();
2121
2122 gtk2_widget = gtk2_get_widget(widget_type);
2123 GtkStyle* style = gtk2_widget->style;
2124 return style->xthickness;
2125 }
2126
2127 static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type)
2128 {
2129 init_containers();
2130
2131 gtk2_widget = gtk2_get_widget(widget_type);
2132 GtkStyle* style = gtk2_widget->style;
2133 return style->ythickness;
2134 }
2135
2136 /*************************************************/
2137 static guint8 recode_color(guint16 channel)
2138 {
2139 return (guint8)(channel>>8);
2140 }
2141
2142 static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,
2143 GtkStateType state_type, ColorType color_type)
2144 {
2145 gint result = 0;
2146 GdkColor *color = NULL;
2147
2148 init_containers();
2149
2150 gtk2_widget = gtk2_get_widget(widget_type);
2151 GtkStyle* style = gtk2_widget->style;
2152
2153 switch (color_type)
2154 {
2155 case FOREGROUND:
2156 color = &(style->fg[state_type]);
2157 break;
2158 case BACKGROUND:
2159 color = &(style->bg[state_type]);
2160 break;
2161 case TEXT_FOREGROUND:
2162 color = &(style->text[state_type]);
2174 color = &(style->mid[state_type]);
2175 break;
2176 case FOCUS:
2177 case BLACK:
2178 color = &(style->black);
2179 break;
2180 case WHITE:
2181 color = &(style->white);
2182 break;
2183 }
2184
2185 if (color)
2186 result = recode_color(color->red) << 16 |
2187 recode_color(color->green) << 8 |
2188 recode_color(color->blue);
2189
2190 return result;
2191 }
2192
2193 /*************************************************/
2194 static jobject create_Boolean(JNIEnv *env, jboolean boolean_value);
2195 static jobject create_Integer(JNIEnv *env, jint int_value);
2196 static jobject create_Long(JNIEnv *env, jlong long_value);
2197 static jobject create_Float(JNIEnv *env, jfloat float_value);
2198 static jobject create_Double(JNIEnv *env, jdouble double_value);
2199 static jobject create_Character(JNIEnv *env, jchar char_value);
2200 static jobject create_Insets(JNIEnv *env, GtkBorder *border);
2201
2202 static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type,
2203 const char* key)
2204 {
2205 init_containers();
2206
2207 gtk2_widget = gtk2_get_widget(widget_type);
2208
2209 GValue value;
2210 value.g_type = 0;
2211
2212 GParamSpec* param = (*fp_gtk_widget_class_find_style_property)(
2213 ((GTypeInstance*)gtk2_widget)->g_class, key);
2214 if( param )
2215 {
2216 (*fp_g_value_init)( &value, param->value_type );
2217 (*fp_gtk_widget_style_get_property)(gtk2_widget, key, &value);
2218
2219 if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN ))
2220 {
2221 gboolean val = (*fp_g_value_get_boolean)(&value);
2222 return create_Boolean(env, (jboolean)val);
2223 }
2224 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR ))
2225 {
2226 gchar val = (*fp_g_value_get_char)(&value);
2307 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED ))
2308 {
2309 gpointer* val = (*fp_g_value_get_boxed)(&value);
2310 printf( "Boxed: %p\n", val );
2311 }
2312 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER ))
2313 {
2314 gpointer* val = (*fp_g_value_get_pointer)(&value);
2315 printf( "Pointer: %p\n", val );
2316 }
2317 else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT ))
2318 {
2319 GObject* val = (GObject*)(*fp_g_value_get_object)(&value);
2320 printf( "Object: %p\n", val );
2321 }*/
2322 }
2323
2324 return NULL;
2325 }
2326
2327 static void gtk2_set_range_value(WidgetType widget_type, jdouble value,
2328 jdouble min, jdouble max, jdouble visible)
2329 {
2330 GtkAdjustment *adj;
2331
2332 gtk2_widget = gtk2_get_widget(widget_type);
2333
2334 adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk2_widget);
2335 adj->value = (gdouble)value;
2336 adj->lower = (gdouble)min;
2337 adj->upper = (gdouble)max;
2338 adj->page_size = (gdouble)visible;
2339 }
2340
2341 /*************************************************/
2342 static jobject create_Object(JNIEnv *env, jmethodID *cid,
2343 const char* class_name,
2344 const char* signature,
2345 jvalue* value)
2346 {
2347 jclass class;
2348 jobject result;
2349
2350 class = (*env)->FindClass(env, class_name);
2351 if( class == NULL )
2352 return NULL; /* can't find/load the class, exception thrown */
2353
2354 if( *cid == NULL)
2355 {
2356 *cid = (*env)->GetMethodID(env, class, "<init>", signature);
2357 if( *cid == NULL )
2358 {
2359 (*env)->DeleteLocalRef(env, class);
2360 return NULL; /* can't find/get the method, exception thrown */
2361 }
2362 }
2425 value.c = char_value;
2426
2427 return create_Object(env, &cid, "java/lang/Character", "(C)V", &value);
2428 }
2429
2430
2431 jobject create_Insets(JNIEnv *env, GtkBorder *border)
2432 {
2433 static jmethodID cid = NULL;
2434 jvalue values[4];
2435
2436 values[0].i = border->top;
2437 values[1].i = border->left;
2438 values[2].i = border->bottom;
2439 values[3].i = border->right;
2440
2441 return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values);
2442 }
2443
2444 /*********************************************/
2445 static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type)
2446 {
2447 init_containers();
2448
2449 gtk2_widget = gtk2_get_widget(widget_type);
2450 jstring result = NULL;
2451 GtkStyle* style = gtk2_widget->style;
2452
2453 if (style && style->font_desc)
2454 {
2455 gchar* val = (*fp_pango_font_description_to_string)(style->font_desc);
2456 result = (*env)->NewStringUTF(env, val);
2457 (*fp_g_free)( val );
2458 }
2459
2460 return result;
2461 }
2462
2463 /***********************************************/
2464 static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
2465 {
2466 jobject result = NULL;
2467 gchar* strval = NULL;
2468
2469 (*fp_g_object_get)(settings, key, &strval, NULL);
2470 result = (*env)->NewStringUTF(env, strval);
2471 (*fp_g_free)(strval);
2472
2473 return result;
2474 }
2475
2476 static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
2477 {
2478 gint intval = NULL;
2479 (*fp_g_object_get)(settings, key, &intval, NULL);
2480 return create_Integer(env, intval);
2481 }
2482
2483 static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
2484 {
2485 gint intval = NULL;
2486 (*fp_g_object_get)(settings, key, &intval, NULL);
2487 return create_Boolean(env, intval);
2488 }
2489
2490 static jobject gtk2_get_setting(JNIEnv *env, Setting property)
2491 {
2492 GtkSettings* settings = (*fp_gtk_settings_get_default)();
2493
2494 switch (property)
2495 {
2496 case GTK_FONT_NAME:
2497 return get_string_property(env, settings, "gtk-font-name");
2498 case GTK_ICON_SIZES:
2499 return get_string_property(env, settings, "gtk-icon-sizes");
2500 case GTK_CURSOR_BLINK:
2501 return get_boolean_property(env, settings, "gtk-cursor-blink");
2502 case GTK_CURSOR_BLINK_TIME:
2503 return get_integer_property(env, settings, "gtk-cursor-blink-time");
2504 }
2505
2506 return NULL;
2507 }
2508
2509 static gboolean gtk2_get_drawable_data(JNIEnv *env, jintArray pixelArray, jint x,
2510 jint y, jint width, jint height, jint jwidth, int dx, int dy, jint scale) {
2511 GdkPixbuf *pixbuf;
2512 jint *ary;
2513
2514 GdkWindow *root = (*fp_gdk_get_default_root_window)();
2515
2516 pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, x, y,
2517 0, 0, width, height);
2518 if (pixbuf && scale != 1) {
2519 GdkPixbuf *scaledPixbuf;
2520 x /= scale;
2521 y /= scale;
2522 width /= scale;
2523 height /= scale;
2524 dx /= scale;
2525 dy /= scale;
2526 scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,
2527 GDK_INTERP_BILINEAR);
2528 (*fp_g_object_unref)(pixbuf);
2529 pixbuf = scaledPixbuf;
2530 }
2531
2532 if (pixbuf) {
2533 int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
2534 int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
2535
2536 if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width
2537 && (*fp_gdk_pixbuf_get_height)(pixbuf) == height
2538 && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8
2539 && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB
2540 && nchan >= 3
2541 ) {
2542 guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
2543
2544 ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
2545 (*env)->ExceptionCheck(env);
2546 if (ary) {
2547 jint _x, _y;
2548 int index;
2549 for (_y = 0; _y < height; _y++) {
2550 for (_x = 0; _x < width; _x++) {
2551 p = pix + _y * stride + _x * nchan;
2552
2553 index = (_y + dy) * jwidth + (_x + dx);
2554 ary[index] = 0xff000000
2555 | (p[0] << 16)
2556 | (p[1] << 8)
2557 | (p[2]);
2558
2559 }
2560 }
2561 (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
2562 (*env)->ExceptionCheck(env);
2563 }
2564 }
2565 (*fp_g_object_unref)(pixbuf);
2566 }
2567 return JNI_FALSE;
2568 }
2569
2570 static GdkWindow* gtk2_get_window(void *widget) {
2571 return ((GtkWidget*)widget)->window;
2572 }
2573
2574 void gtk2_init(GtkApi* gtk) {
2575 gtk->version = GTK_2;
2576
2577 gtk->show_uri_load = >k2_show_uri_load;
2578 gtk->unload = >k2_unload;
2579 gtk->flush_event_loop = &flush_gtk_event_loop;
2580 gtk->gtk_check_version = fp_gtk_check_version;
2581 gtk->get_setting = >k2_get_setting;
2582
2583 gtk->paint_arrow = >k2_paint_arrow;
2584 gtk->paint_box = >k2_paint_box;
2585 gtk->paint_box_gap = >k2_paint_box_gap;
2586 gtk->paint_expander = >k2_paint_expander;
2587 gtk->paint_extension = >k2_paint_extension;
2588 gtk->paint_flat_box = >k2_paint_flat_box;
2589 gtk->paint_focus = >k2_paint_focus;
2590 gtk->paint_handle = >k2_paint_handle;
2591 gtk->paint_hline = >k2_paint_hline;
2592 gtk->paint_vline = >k2_paint_vline;
2593 gtk->paint_option = >k2_paint_option;
2594 gtk->paint_shadow = >k2_paint_shadow;
2595 gtk->paint_slider = >k2_paint_slider;
2596 gtk->paint_background = >k_paint_background;
2597 gtk->paint_check = >k2_paint_check;
2598 gtk->set_range_value = >k2_set_range_value;
2599
2600 gtk->init_painting = >k2_init_painting;
2601 gtk->copy_image = >k2_copy_image;
2602
2603 gtk->get_xthickness = >k2_get_xthickness;
2604 gtk->get_ythickness = >k2_get_ythickness;
2605 gtk->get_color_for_state = >k2_get_color_for_state;
2606 gtk->get_class_value = >k2_get_class_value;
2607
2608 gtk->get_pango_font_name = >k2_get_pango_font_name;
2609 gtk->get_icon_data = >k2_get_icon_data;
2610 gtk->get_file_icon_data = >k2_get_file_icon_data;
2611 gtk->gdk_threads_enter = fp_gdk_threads_enter;
2612 gtk->gdk_threads_leave = fp_gdk_threads_leave;
2613 gtk->gtk_show_uri = fp_gtk_show_uri;
2614 gtk->get_drawable_data = >k2_get_drawable_data;
2615 gtk->g_free = fp_g_free;
2616
2617 gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename;
2618 gtk->gtk_widget_hide = fp_gtk_widget_hide;
2619 gtk->gtk_main_quit = fp_gtk_main_quit;
2620 gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new;
2621 gtk->gtk_file_chooser_set_current_folder =
2622 fp_gtk_file_chooser_set_current_folder;
2623 gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename;
2624 gtk->gtk_file_chooser_set_current_name =
2625 fp_gtk_file_chooser_set_current_name;
2626 gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom;
2627 gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter;
2628 gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type;
2629 gtk->gtk_file_filter_new = fp_gtk_file_filter_new;
2630 gtk->gtk_file_chooser_set_do_overwrite_confirmation =
2631 fp_gtk_file_chooser_set_do_overwrite_confirmation;
2632 gtk->gtk_file_chooser_set_select_multiple =
2633 fp_gtk_file_chooser_set_select_multiple;
2634 gtk->gtk_file_chooser_get_current_folder =
2635 fp_gtk_file_chooser_get_current_folder;
2636 gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames;
2637 gtk->gtk_g_slist_length = fp_gtk_g_slist_length;
2638 gtk->g_signal_connect_data = fp_g_signal_connect_data;
2639 gtk->gtk_widget_show = fp_gtk_widget_show;
2640 gtk->gtk_main = fp_gtk_main;
2641 gtk->gtk_main_level = fp_gtk_main_level;
2642 gtk->g_path_get_dirname = fp_g_path_get_dirname;
2643 gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid;
2644 gtk->gtk_widget_destroy = fp_gtk_widget_destroy;
2645 gtk->gtk_window_present = fp_gtk_window_present;
2646 gtk->gtk_window_move = fp_gtk_window_move;
2647 gtk->gtk_window_resize = fp_gtk_window_resize;
2648 gtk->get_window = >k2_get_window;
2649
2650 }
|