/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <dlfcn.h>
#include <setjmp.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "gtk2_interface.h"
#include "java_awt_Transparency.h"
#include "jvm_md.h"
#include "sizecalc.h"
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
/* SynthConstants */
static jmp_buf j;
/* Widgets */
/* Paint system */
static int gtk2_pixbuf_width = 0;
static int gtk2_pixbuf_height = 0;
/* Static buffer for conversion from java.lang.String to UTF-8 */
/*******************/
enum GtkWidgetType
{
};
/*************************
* Glib function pointers
*************************/
const gchar *first_property_name,
...);
/************************
* GDK function pointers
************************/
/************************
* Gtk function pointers
************************/
/* Painting */
/* Widget creation */
/* Other widget operations */
const gchar *first_property_name, ...);
static void (*fp_gtk_widget_class_install_style_property)(
static char* (*fp_pango_font_description_to_string)(
const PangoFontDescription* fd);
/* Method bodies */
{
{
#ifdef INTERNAL_BUILD
#endif /* INTERNAL_BUILD */
}
return convertionBuffer;
}
{
}
/* This is a workaround for the bug:
* This bug is specific to Linux, but there is no harm in
* applying this workaround on Solaris as well.
*/
{
if (!result)
return result;
}
{
if (!result)
return result;
}
{
if (gtk2_libhandle != NULL) {
/* We've already successfully opened the GTK libs, so return true. */
return TRUE;
} else {
return FALSE;
}
}
/* Check for GTK 2.2+ */
}
return result;
}
}
/**
* Functions for sun_awt_X11_GtkFileDialogPeer.c
*/
void gtk2_file_chooser_load()
{
"gtk_file_chooser_get_filename");
"gtk_file_chooser_set_current_folder");
"gtk_file_chooser_set_filename");
"gtk_file_chooser_set_current_name");
"gtk_file_chooser_set_do_overwrite_confirmation");
}
"gtk_file_chooser_set_select_multiple");
"gtk_file_chooser_get_current_folder");
"gtk_file_chooser_get_filenames");
}
{
int i;
int (*handler)();
int (*io_handler)();
char *gtk_modules_env;
if (gtk2_libhandle == NULL) {
if (gtk2_libhandle == NULL)
return FALSE;
}
if (gthread_libhandle == NULL) {
if (gthread_libhandle == NULL)
return FALSE;
}
if (setjmp(j) == 0)
{
/* Check for GTK 2.2+ */
}
/* GLib */
dl_symbol("g_main_context_iteration");
/* GDK */
dl_symbol("gdk_pixbuf_get_from_drawable");
dl_symbol("gdk_rgb_gc_set_foreground");
/* Pixbuf */
dl_symbol("gdk_pixbuf_new_from_file");
dl_symbol("gdk_pixbuf_get_rowstride");
dl_symbol("gdk_pixbuf_get_has_alpha");
dl_symbol("gdk_pixbuf_get_bits_per_sample");
dl_symbol("gdk_pixbuf_get_n_channels");
/* GTK painting */
dl_symbol("gtk_style_apply_default_background");
/* GTK widgets */
dl_symbol("gtk_check_menu_item_new");
dl_symbol("gtk_color_selection_dialog_new");
dl_symbol("gtk_menu_item_set_submenu");
dl_symbol("gtk_progress_bar_new");
dl_symbol("gtk_progress_bar_set_orientation");
dl_symbol("gtk_radio_button_new");
dl_symbol("gtk_radio_menu_item_new");
dl_symbol("gtk_scrolled_window_new");
dl_symbol("gtk_separator_menu_item_new");
dl_symbol("gtk_toggle_button_new");
dl_symbol("gtk_menu_shell_append");
dl_symbol("gtk_widget_render_icon");
dl_symbol("gtk_widget_set_name");
dl_symbol("gtk_widget_set_parent");
dl_symbol("gtk_widget_set_direction");
dl_symbol("gtk_widget_style_get");
dl_symbol("gtk_widget_class_install_style_property");
dl_symbol("gtk_widget_class_find_style_property");
dl_symbol("gtk_widget_style_get_property");
dl_symbol("pango_font_description_to_string");
dl_symbol("gtk_settings_get_default");
dl_symbol("gtk_widget_get_settings");
dl_symbol("gtk_widget_size_request");
dl_symbol("gtk_range_get_adjustment");
/**
* GLib thread system
*/
/**
* Functions for sun_awt_X11_GtkFileDialogPeer.c
*/
// The current GtkFileChooser is available from GTK+ 2.4
}
/* Some functions may be missing in pre-2.4 GTK.
We handle them specially here.
*/
if (fp_gtk_combo_box_new == NULL) {
}
if (fp_gtk_combo_box_entry_new == NULL) {
}
if (fp_gtk_separator_tool_item_new == NULL) {
dl_symbol("gtk_vseparator_new");
}
}
/* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION
* Otherwise we can check the return value of setjmp method.
*/
else
{
return FALSE;
}
/*
* Strip the AT-SPI GTK_MODULEs if present
*/
{
/* the new env will be smaller than the old one */
{
/* careful, strtok modifies its args */
/* strip out 'atk-bridge' and 'gail' */
{
{
}
}
if (tmp_env)
{
}
}
}
}
/*
* GTK should be initialized with gtk_init_check() before use.
*
* gtk_init_check installs its own error handlers. It is critical that
* we preserve error handler set from AWT. Otherwise we'll crash on
* BadMatch errors which we would normally ignore. The IO error handler
* is preserved here, too, just for consistency.
*/
// Init the thread system to use GLib in a thread-safe mode
if (!flag_g_thread_get_initialized) {
//According the GTK documentation, gdk_threads_init() should be
//called before gtk_init() or gtk_init_check()
}
}
/* Initialize widget array. */
for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)
{
gtk2_widgets[i] = NULL;
}
return result;
}
int gtk2_unload()
{
int i;
char *gtk2_error;
if (!gtk2_libhandle)
return TRUE;
/* Release painting objects */
if (gtk2_white_pixmap != NULL) {
}
gtk2_pixbuf_width = 0;
gtk2_pixbuf_height = 0;
if (gtk2_window != NULL) {
/* Destroying toplevel widget will destroy all contained widgets */
/* Unset some static data so they get reinitialized on next load */
gtk2_window = NULL;
}
dlerror();
{
return FALSE;
}
return TRUE;
}
/* Dispatch all pending events from the GTK event loop.
* This is needed to catch theme change and update widgets' style.
*/
void flush_gtk_event_loop()
{
}
/*
* Initialize components of containment hierarchy. This creates a GtkFixed
* inside a GtkWindow. All widgets get realized.
*/
static void init_containers()
{
if (gtk2_window == NULL)
{
(GtkWidget *)gtk2_fixed);
}
}
/*
* Ensure everything is ready for drawing an element of the specified width
* and height.
*
* We should somehow handle translucent images. GTK can draw to X Drawables
* only, which don't support alpha. When we retrieve the image back from
* the server, translucency information is lost. There're several ways to
* work around this:
* 1) Subclass GdkPixmap and cache translucent objects on client side. This
* requires us to implement parts of X server drawing logic on client side.
* Many X requests can potentially be "translucent"; e.g. XDrawLine with
* fill=tile and a translucent tile is a "translucent" operation, whereas
* XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some
* do) intermix transparent and opaque operations which makes caching even
* more problematic.
* 2) Use Xorg 32bit ARGB visual when available. GDK has no native support
* for it (as of version 2.6). Also even in JDS 3 Xorg does not support
* these visuals by default, which makes optimizing for them pointless.
* We can consider doing this at a later point when ARGB visuals become more
* popular.
* 3') GTK has plans to use Cairo as its graphical backend (presumably in
* 2.8), and Cairo supports alpha. With it we could also get rid of the
* unnecessary round trip to server and do all the drawing on client side.
* 4) For now we draw to two different pixmaps and restore alpha channel by
* comparing results. This can be optimized by using subclassed pixmap and
* doing the second drawing only if necessary.
*/
{
{
{
snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height);
return;
}
if (gtk2_white_pixmap != NULL) {
/* free old stuff */
}
}
/* clear the pixmaps */
(*fp_g_object_unref)(gc);
(*fp_g_object_unref)(gc);
}
/*
* Restore image from white and black pixmaps and copy it into destination
* buffer. This method compares two pixbufs taken from white and black
* pixmaps and decodes color and alpha components. Pixbufs are RGB without
* alpha, destination buffer is ABGR.
*
* The return value is the transparency type of the resulting image, either
* one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and
* java_awt_Transparency_TRANSLUCENT.
*/
{
gint i, j, r, g, b;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
switch (alpha) {
case 0: /* transparent pixel */
r = g = b = 0;
black += 3;
white += 3;
break;
case 0xff: /* opaque pixel */
r = r2;
g = *black++;
b = *black++;
black++;
white += 3;
break;
default: /* translucent pixel */
black++;
white += 3;
is_bitmask = FALSE;
break;
}
}
}
return is_opaque ? java_awt_Transparency_OPAQUE :
}
static void
{
/*
* Some engines (inexplicably) look at the direction of the widget's
* parent, so we need to set the direction of both the widget and its
* parent.
*/
}
}
/*
* Initializes the widget to correct state for some engines.
* This is a pure empirical method.
*/
{
if (widget_type == RADIO_BUTTON ||
widget_type == CHECK_BOX ||
widget_type == TOGGLE_BUTTON) {
}
if ((synth_state & FOCUSED) != 0) {
} else {
}
} else if ((synth_state & DISABLED) != 0) {
} else {
}
}
/* GTK state_type filter */
{
if ((synth_state & DISABLED) != 0) {
} else if ((synth_state & PRESSED) != 0) {
} else if ((synth_state & MOUSE_OVER) != 0) {
}
return result;
}
/* GTK shadow_type filter */
{
if ((synth_state & SELECTED) != 0) {
}
return result;
}
{
{
}
return arrow;
}
{
return (GtkAdjustment *)
}
/**
* Returns a pointer to the cached native widget for the specified widget
* type.
*/
{
switch (widget_type)
{
case BUTTON:
case TABLE_HEADER:
{
}
break;
case CHECK_BOX:
{
(*fp_gtk_check_button_new)();
}
break;
case CHECK_BOX_MENU_ITEM:
{
}
break;
/************************************************************
* Creation a dedicated color chooser is dangerous because
* it deadlocks the EDT
************************************************************/
/* case COLOR_CHOOSER:
if (init_result =
(NULL == gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]))
{
gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] =
(*fp_gtk_color_selection_dialog_new)(NULL);
}
result = gtk2_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE];
break;*/
case COMBO_BOX:
{
(*fp_gtk_combo_box_new)();
}
break;
case COMBO_BOX_ARROW_BUTTON:
if (init_result =
{
(*fp_gtk_toggle_button_new)();
}
break;
case COMBO_BOX_TEXT_FIELD:
if (init_result =
{
(*fp_gtk_entry_new)();
}
break;
case DESKTOP_ICON:
case LABEL:
{
(*fp_gtk_label_new)(NULL);
}
break;
case DESKTOP_PANE:
case PANEL:
case ROOT_PANE:
{
/* There is no constructor for a container type. I've
* choosen GtkFixed container since it has a default
* constructor.
*/
(*fp_gtk_fixed_new)();
}
break;
case EDITOR_PANE:
case TEXT_AREA:
case TEXT_PANE:
{
(*fp_gtk_text_view_new)();
}
break;
case FORMATTED_TEXT_FIELD:
case PASSWORD_FIELD:
case TEXT_FIELD:
{
(*fp_gtk_entry_new)();
}
break;
case HANDLE_BOX:
{
(*fp_gtk_handle_box_new)();
}
break;
case HSCROLL_BAR:
case HSCROLL_BAR_BUTTON_LEFT:
case HSCROLL_BAR_BUTTON_RIGHT:
case HSCROLL_BAR_TRACK:
case HSCROLL_BAR_THUMB:
{
}
break;
case HSEPARATOR:
{
(*fp_gtk_hseparator_new)();
}
break;
case HSLIDER:
case HSLIDER_THUMB:
case HSLIDER_TRACK:
{
(*fp_gtk_hscale_new)(NULL);
}
break;
case HSPLIT_PANE_DIVIDER:
case SPLIT_PANE:
{
}
break;
case IMAGE:
{
}
break;
case INTERNAL_FRAME:
{
}
break;
case TOOL_TIP:
{
}
break;
case LIST:
case TABLE:
case TREE:
case TREE_CELL:
{
(*fp_gtk_tree_view_new)();
}
break;
case TITLED_BORDER:
{
}
break;
case POPUP_MENU:
{
(*fp_gtk_menu_new)();
}
break;
case MENU:
case MENU_ITEM:
case MENU_ITEM_ACCELERATOR:
{
(*fp_gtk_menu_item_new)();
}
break;
case MENU_BAR:
{
(*fp_gtk_menu_bar_new)();
}
break;
case COLOR_CHOOSER:
case OPTION_PANE:
{
(*fp_gtk_dialog_new)();
}
break;
case POPUP_MENU_SEPARATOR:
if (init_result =
{
}
break;
case HPROGRESS_BAR:
{
(*fp_gtk_progress_bar_new)();
}
break;
case VPROGRESS_BAR:
{
(*fp_gtk_progress_bar_new)();
/*
* Vertical JProgressBars always go bottom-to-top,
* regardless of the ComponentOrientation.
*/
}
break;
case RADIO_BUTTON:
{
}
break;
case RADIO_BUTTON_MENU_ITEM:
if (init_result =
{
}
break;
case SCROLL_PANE:
if (init_result =
{
}
break;
case SPINNER:
case SPINNER_ARROW_BUTTON:
case SPINNER_TEXT_FIELD:
{
(*fp_gtk_spin_button_new)(NULL, 0, 0);
}
break;
case TABBED_PANE:
case TABBED_PANE_TAB_AREA:
case TABBED_PANE_CONTENT:
case TABBED_PANE_TAB:
{
(*fp_gtk_notebook_new)(NULL);
}
break;
case TOGGLE_BUTTON:
{
}
break;
case TOOL_BAR:
case TOOL_BAR_DRAG_WINDOW:
{
(*fp_gtk_toolbar_new)(NULL);
}
break;
case TOOL_BAR_SEPARATOR:
if (init_result =
{
}
break;
case VIEWPORT:
{
}
break;
case VSCROLL_BAR:
case VSCROLL_BAR_BUTTON_UP:
case VSCROLL_BAR_BUTTON_DOWN:
case VSCROLL_BAR_TRACK:
case VSCROLL_BAR_THUMB:
{
}
break;
case VSEPARATOR:
{
(*fp_gtk_vseparator_new)();
}
break;
case VSLIDER:
case VSLIDER_THUMB:
case VSLIDER_TRACK:
{
(*fp_gtk_vscale_new)(NULL);
}
/*
* Vertical JSliders start at the bottom, while vertical
* GtkVScale widgets start at the top (by default), so to fix
* this we set the "inverted" flag to get the Swing behavior.
*/
break;
case VSPLIT_PANE_DIVIDER:
{
}
break;
default:
break;
}
{
if (widget_type == RADIO_BUTTON_MENU_ITEM ||
widget_type == MENU_ITEM ||
widget_type == MENU ||
{
}
else if (widget_type == POPUP_MENU)
{
}
else if (widget_type == COMBO_BOX_ARROW_BUTTON ||
{
/*
* in order to trick engines into thinking it's a real combobox
*/
} else {
}
}
else if (widget_type != TOOL_TIP &&
widget_type != INTERNAL_FRAME &&
{
}
}
return result;
}
{
static int w, h;
else
switch (widget_type)
{
case SPINNER_ARROW_BUTTON:
x = 1;
height -= 2;
width -= 3;
w = width / 2;
w -= w % 2 - 1;
h = (w + 1) / 2;
break;
case HSCROLL_BAR_BUTTON_LEFT:
case HSCROLL_BAR_BUTTON_RIGHT:
case VSCROLL_BAR_BUTTON_UP:
case VSCROLL_BAR_BUTTON_DOWN:
w = width / 2;
h = height / 2;
break;
case COMBO_BOX_ARROW_BUTTON:
case TABLE:
x = 1;
break;
default:
w = width;
h = height;
break;
}
x += (width - w) / 2;
y += (height - h) / 2;
x, y, w, h);
x, y, w, h);
}
{
/*
* The clearlooks engine sometimes looks at the widget's state field
* instead of just the state_type variable that we pass in, so to account
* for those cases we set the widget's state field accordingly. The
*/
if (widget_type == HSLIDER_TRACK) {
/*
* For horizontal JSliders with right-to-left orientation, we need
* to set the "inverted" flag to match the native GTK behavior where
* the foreground highlight is on the right side of the slider thumb.
* This is needed especially for the ubuntulooks engine, which looks
* exclusively at the "inverted" flag to determine on which side of
* the thumb to paint the highlight...
*/
/*
* Note however that other engines like clearlooks will look at both
* the "inverted" field and the text direction to determine how
* the foreground highlight is painted:
* !inverted && ltr --> paint highlight on left side
* !inverted && rtl --> paint highlight on right side
* inverted && ltr --> paint highlight on right side
* inverted && rtl --> paint highlight on left side
* So the only way to reliably get the desired results for horizontal
* JSlider (i.e., highlight on left side for LTR ComponentOrientation
* and highlight on right side for RTL ComponentOrientation) is to
* always override text direction as LTR, and then set the "inverted"
* flag accordingly (as we have done above).
*/
}
/*
* Some engines (e.g. clearlooks) will paint the shadow of certain
* widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the
* the text direction.
*/
switch (widget_type) {
case BUTTON:
if (synth_state & DEFAULT) {
} else {
}
break;
case TOGGLE_BUTTON:
break;
case HSCROLL_BAR_BUTTON_LEFT:
/*
* The clearlooks engine will draw a "left" button when:
* x == w->allocation.x
*
* The ubuntulooks engine will draw a "left" button when:
* [x,y,width,height]
* intersects
* [w->alloc.x,w->alloc.y,width,height]
*
* The values that are set below should ensure that a "left"
* button is rendered for both of these (and other) engines.
*/
gtk2_widget->allocation.x = x;
gtk2_widget->allocation.y = y;
break;
case HSCROLL_BAR_BUTTON_RIGHT:
/*
* The clearlooks engine will draw a "right" button when:
* x + width == w->allocation.x + w->allocation.width
*
* The ubuntulooks engine will draw a "right" button when:
* [x,y,width,height]
* does not intersect
* [w->alloc.x,w->alloc.y,width,height]
* but does intersect
* [w->alloc.x+width,w->alloc.y,width,height]
*
* The values that are set below should ensure that a "right"
* button is rendered for both of these (and other) engines.
*/
gtk2_widget->allocation.y = 0;
break;
case VSCROLL_BAR_BUTTON_UP:
/*
* The clearlooks engine will draw an "up" button when:
* y == w->allocation.y
*
* The ubuntulooks engine will draw an "up" button when:
* [x,y,width,height]
* intersects
* [w->alloc.x,w->alloc.y,width,height]
*
* The values that are set below should ensure that an "up"
* button is rendered for both of these (and other) engines.
*/
gtk2_widget->allocation.x = x;
gtk2_widget->allocation.y = y;
break;
case VSCROLL_BAR_BUTTON_DOWN:
/*
* The clearlooks engine will draw a "down" button when:
* y + height == w->allocation.y + w->allocation.height
*
* The ubuntulooks engine will draw a "down" button when:
* [x,y,width,height]
* does not intersect
* [w->alloc.x,w->alloc.y,width,height]
* but does intersect
* [w->alloc.x,w->alloc.y+height,width,height]
*
* The values that are set below should ensure that a "down"
* button is rendered for both of these (and other) engines.
*/
gtk2_widget->allocation.x = x;
break;
default:
break;
}
/*
* Reset the text direction to the default value so that we don't
* accidentally affect other operations and widgets.
*/
}
{
/* Clearlooks needs a real clip area to paint the gap properly */
}
{
}
{
}
{
}
{
}
{
if (has_focus)
else
}
{
}
{
}
{
}
{
}
{
/*
* The clearlooks engine sometimes looks at the widget's state field
* instead of just the state_type variable that we pass in, so to account
* for those cases we set the widget's state field accordingly. The
* flags field is similarly important for things like focus state.
*/
/*
* Some engines (e.g. clearlooks) will paint the shadow of certain
* widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the
* the text direction.
*/
switch (widget_type) {
case COMBO_BOX_TEXT_FIELD:
case FORMATTED_TEXT_FIELD:
case PASSWORD_FIELD:
case SPINNER_TEXT_FIELD:
case TEXT_FIELD:
if (synth_state & FOCUSED) {
} else {
}
break;
default:
break;
}
/*
* Reset the text direction to the default value so that we don't
* accidentally affect other operations and widgets.
*/
}
{
}
{
}
{
}
{
}
/*************************************************/
{
return style->xthickness;
}
{
return style->ythickness;
}
/*************************************************/
{
}
{
switch (color_type)
{
case FOREGROUND:
break;
case BACKGROUND:
break;
case TEXT_FOREGROUND:
break;
case TEXT_BACKGROUND:
break;
case LIGHT:
break;
case DARK:
break;
case MID:
break;
case FOCUS:
case BLACK:
break;
case WHITE:
break;
}
if (color)
return result;
}
/*************************************************/
{
if( param )
{
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
/* We suppose that all values come in C locale and
* utf-8 representation of a string is the same as
* the string itself. If this isn't so we should
* use g_convert.
*/
}
{
}
/* TODO: Other types are not supported yet.*/
/* else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM ))
{
GParamSpec* val = (*fp_g_value_get_param)(&value);
printf( "Param: %p\n", val );
}
else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED ))
{
gpointer* val = (*fp_g_value_get_boxed)(&value);
printf( "Boxed: %p\n", val );
}
else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER ))
{
gpointer* val = (*fp_g_value_get_pointer)(&value);
printf( "Pointer: %p\n", val );
}
else if( (*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT ))
{
GObject* val = (GObject*)(*fp_g_value_get_object)(&value);
printf( "Object: %p\n", val );
}*/
}
return NULL;
}
{
}
/*************************************************/
const char* class_name,
const char* signature,
{
{
{
}
}
return result;
}
{
value.z = boolean_value;
}
{
}
{
value.j = long_value;
}
{
value.f = float_value;
}
{
value.d = double_value;
}
{
value.c = char_value;
}
{
}
/*********************************************/
{
{
}
return result;
}
/***********************************************/
{
return result;
}
/*
jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
{
gint intval = NULL;
(*fp_g_object_get)(settings, key, &intval, NULL);
return create_Integer(env, intval);
}*/
{
switch (property)
{
case GTK_FONT_NAME:
case GTK_ICON_SIZES:
}
return NULL;
}