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