blob: 032ce4387b64574eb117380785e4b3e3c603bb93 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2013 IBM Corporation and others. All rights reserved.
* The contents of this file are made available under the terms
* of the GNU Lesser General Public License (LGPL) Version 2.1 that
* accompanies this distribution (lgpl-v21.txt). The LGPL is also
* available at http://www.gnu.org/licenses/lgpl.html. If the version
* of the LGPL at http://www.gnu.org is different to the version of
* the LGPL accompanying this distribution and there is any conflict
* between the two license versions, the terms of the LGPL accompanying
* this distribution shall govern.
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
#include "swt.h"
#include "os_structs.h"
#include "os_stats.h"
#define OS_NATIVE(func) Java_org_eclipse_swt_internal_gtk_OS_##func
#ifndef NO__1call_1get_1size
JNIEXPORT void JNICALL OS_NATIVE(_1call_1get_1size)
(JNIEnv *env, jclass that, jintLong arg0, jintLong arg1, jintLong arg2, jintLong arg3, jintLong arg4, jintLong arg5, jintLong arg6, jintLong arg7)
{
/*
* Bug in Solaris. For some reason, the assembler generated for this function (when not putting the parameters in the stack) crashes.
* It seems that this is caused by a bug in the Sun Studio Compiler when the optimization level is greater or equal to two.
* The fix is rewrite the function passing all parameters on the stack. Alternatively, the problem could be fixed by lowering the optimization level,
* but this solution would significantly increase the size of the library.
*/
const GdkRectangle rect;
gint x, y, width, height;
const GdkRectangle *lprect = NULL;
gint* lpx = NULL;
gint* lpy = NULL;
gint* lpwidth = NULL;
gint* lpheight = NULL;
OS_NATIVE_ENTER(env, that, _1call_1get_1size_FUNC);
if (arg3) lprect = ▭
if (arg4) lpx = &x;
if (arg5) lpy = &y;
if (arg6) lpwidth = &width;
if (arg7) lpheight = &height;
((void (*)(GtkCellRenderer *, GtkWidget *, const GdkRectangle *, gint *, gint *, gint *, gint *))arg0)((GtkCellRenderer *)arg1, (GtkWidget *)arg2, lprect, lpx, lpy, lpwidth, lpheight);
if (arg3) *((GdkRectangle *)arg3) = rect;
if (arg4) *((gint *)arg4) = x;
if (arg5) *((gint *)arg5) = y;
if (arg6) *((gint *)arg6) = width;
if (arg7) *((gint *)arg7) = height;
OS_NATIVE_EXIT(env, that, _1call_1get_1size_FUNC);
}
#endif
#ifndef NO_GDK_1WINDOWING_1X11
JNIEXPORT jboolean JNICALL OS_NATIVE(GDK_1WINDOWING_1X11)
(JNIEnv *env, jclass that)
{
jboolean rc;
OS_NATIVE_ENTER(env, that, GDK_1WINDOWING_1X11_FUNC)
#ifdef GDK_WINDOWING_X11
rc = (jboolean)1;
#else
rc = (jboolean)0;
#endif
OS_NATIVE_EXIT(env, that, GDK_1WINDOWING_1X11_FUNC)
return rc;
}
#endif
#ifndef NO_GDK_1WINDOWING_1WAYLAND
JNIEXPORT jboolean JNICALL OS_NATIVE(GDK_1WINDOWING_1WAYLAND)
(JNIEnv *env, jclass that)
{
jboolean rc;
OS_NATIVE_ENTER(env, that, GDK_1WINDOWING_1WAYLAND_FUNC)
#ifdef GDK_WINDOWING_WAYLAND
rc = (jboolean)1;
#else
rc = (jboolean)0;
#endif
OS_NATIVE_EXIT(env, that, GDK_1WINDOWING_1WAYLAND_FUNC)
return rc;
}
#endif
#ifndef NO_imContextNewProc_1CALLBACK
static jintLong superIMContextNewProc;
static GtkIMContext* lastIMContext;
static GtkIMContext* imContextNewProc (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
GtkIMContext* context = ((GtkIMContext * (*)(GType, guint, GObjectConstructParam *))superIMContextNewProc)(type, n_construct_properties, construct_properties);
lastIMContext = context;
return context;
}
#ifndef NO_imContextLast
JNIEXPORT jintLong JNICALL OS_NATIVE(imContextLast)
(JNIEnv *env, jclass that)
{
jintLong rc = 0;
OS_NATIVE_ENTER(env, that, imContextLast_FUNC);
rc = (jintLong)lastIMContext;
OS_NATIVE_EXIT(env, that, imContextLast_FUNC);
return rc;
}
#endif
JNIEXPORT jintLong JNICALL OS_NATIVE(imContextNewProc_1CALLBACK)
(JNIEnv *env, jclass that, jintLong arg0)
{
jintLong rc = 0;
OS_NATIVE_ENTER(env, that, imContextNewProc_1CALLBACK_FUNC);
superIMContextNewProc = arg0;
rc = (jintLong)imContextNewProc;
OS_NATIVE_EXIT(env, that, imContextNewProc_1CALLBACK_FUNC);
return rc;
}
#endif
#ifndef NO_pangoLayoutNewProc_1CALLBACK
static jintLong superPangoLayoutNewProc;
static PangoLayout * pangoLayoutNewProc (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
PangoLayout* layout = ((PangoLayout * (*)(GType, guint, GObjectConstructParam *))superPangoLayoutNewProc)(type, n_construct_properties, construct_properties);
pango_layout_set_auto_dir (layout, 0);
return layout;
}
JNIEXPORT jintLong JNICALL OS_NATIVE(pangoLayoutNewProc_1CALLBACK)
(JNIEnv *env, jclass that, jintLong arg0)
{
jintLong rc = 0;
OS_NATIVE_ENTER(env, that, pangoLayoutNewProc_1CALLBACK_FUNC);
superPangoLayoutNewProc = arg0;
rc = (jintLong)pangoLayoutNewProc;
OS_NATIVE_EXIT(env, that, pangoLayoutNewProc_1CALLBACK_FUNC);
return rc;
}
#endif
#ifndef NO_pangoFontFamilyNewProc_1CALLBACK
static jintLong superPangoFontFamilyNewProc;
static PangoFontFamily * pangoFontFamilyNewProc (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
PangoFontFamily* fontFamily = ((PangoFontFamily * (*)(GType, guint, GObjectConstructParam *))superPangoFontFamilyNewProc)(type, n_construct_properties, construct_properties);
return fontFamily;
}
JNIEXPORT jintLong JNICALL OS_NATIVE(pangoFontFamilyNewProc_1CALLBACK)
(JNIEnv *env, jclass that, jintLong arg0)
{
jintLong rc = 0;
OS_NATIVE_ENTER(env, that, pangoFontFamilyNewProc_1CALLBACK_FUNC);
superPangoFontFamilyNewProc = arg0;
rc = (jintLong)pangoFontFamilyNewProc;
OS_NATIVE_EXIT(env, that, pangoFontFamilyNewProc_1CALLBACK_FUNC);
return rc;
}
#endif
#ifndef NO_pangoFontFaceNewProc_1CALLBACK
static jintLong superPangoFontFaceNewProc;
static PangoFontFace * pangoFontFaceNewProc (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
PangoFontFace* fontFace = ((PangoFontFace * (*)(GType, guint, GObjectConstructParam *))superPangoFontFaceNewProc)(type, n_construct_properties, construct_properties);
return fontFace;
}
JNIEXPORT jintLong JNICALL OS_NATIVE(pangoFontFaceNewProc_1CALLBACK)
(JNIEnv *env, jclass that, jintLong arg0)
{
jintLong rc = 0;
OS_NATIVE_ENTER(env, that, pangoFontFaceNewProc_1CALLBACK_FUNC);
superPangoFontFaceNewProc = arg0;
rc = (jintLong)pangoFontFaceNewProc;
OS_NATIVE_EXIT(env, that, pangoFontFaceNewProc_1CALLBACK_FUNC);
return rc;
}
#endif
#ifndef NO_printerOptionWidgetNewProc_1CALLBACK
static jintLong superPrinterOptionWidgetNewProc;
static GType * printerOptionWidgetNewProc (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
GType* printerOptionWidget = ((GType * (*)(GType, guint, GObjectConstructParam *))superPrinterOptionWidgetNewProc)(type, n_construct_properties, construct_properties);
return printerOptionWidget;
}
JNIEXPORT jintLong JNICALL OS_NATIVE(printerOptionWidgetNewProc_1CALLBACK)
(JNIEnv *env, jclass that, jintLong arg0)
{
jintLong rc = 0;
OS_NATIVE_ENTER(env, that, printerOptionWidgetNewProc_1CALLBACK_FUNC);
superPrinterOptionWidgetNewProc = arg0;
rc = (jintLong)printerOptionWidgetNewProc;
OS_NATIVE_EXIT(env, that, printerOptionWidgetNewProc_1CALLBACK_FUNC);
return rc;
}
#endif
#ifndef NO__1gtk_1cell_1layout_1set_1attributes
JNIEXPORT void JNICALL OS_NATIVE(_1gtk_1cell_1layout_1set_1attributes)
(JNIEnv *env, jclass that, jintLong arg0, jintLong arg1, jbyteArray arg2, jint arg3, jintLong arg4)
{
jbyte *lparg2=NULL;
OS_NATIVE_ENTER(env, that, _1gtk_1cell_1layout_1set_1attributes_FUNC);
if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail;
/*
gtk_cell_layout_set_attributes(arg0, arg1, lparg2, arg3, arg4);
*/
{
/*
* On AMD64, it is critical that functions which have a variable number of
* arguments, indicated by '...', include the '...' in their prototype. This
* changes the calling convention, and leaving it out will cause crashes.
*
* For some reason, we must also explicitly declare all of the arguments we
* are passing in, otherwise it crashes.
*/
typedef void (*FPTR)(jintLong, jintLong, jbyte *, jint, jintLong, ...);
OS_LOAD_FUNCTION(fp, gtk_cell_layout_set_attributes)
if (fp) {
((FPTR)fp)(arg0, arg1, lparg2, arg3, arg4);
}
}
fail:
if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, 0);
OS_NATIVE_EXIT(env, that, _1gtk_1cell_1layout_1set_1attributes_FUNC);
}
#endif
glong g_utf16_strlen(const gchar *str, glong max) {
const gchar *s = str;
guchar ch;
glong offset = 0;
if (!s || max == 0) return 0;
if (max < 0) {
while (*s) {
if (0xf0 <= *(guchar*)s && *(guchar*)s <= 0xfd) offset++;
s = g_utf8_next_char (s);
offset++;
}
} else {
while (*s) {
ch = *(guchar*)s;
s = g_utf8_next_char (s);
if (s - str > max) break;
if (0xf0 <= ch && ch <= 0xfd) offset++;
offset++;
}
}
return offset;
}
glong g_utf16_pointer_to_offset(const gchar *str, const gchar * pos) {
const gchar *s = str;
glong offset = 0;
if (!s || !pos) return 0;
while (s < pos && *s) {
if (0xf0 <= *(guchar*)s && *(guchar*)s <= 0xfd) offset++;
s = g_utf8_next_char (s);
offset++;
}
return offset;
}
gchar* g_utf16_offset_to_pointer(const gchar* str, glong offset) {
const gchar *s = str;
if (!s) return 0;
while (offset-- > 0 && *s) {
if (0xf0 <= *(guchar*)s && *(guchar*)s <= 0xfd) offset--;
s = g_utf8_next_char (s);
}
return (gchar *)s;
}
glong g_utf16_offset_to_utf8_offset(const gchar* str, glong offset) {
glong r = 0;
const gchar *s = str;
if (!s) return 0;
while (offset-- > 0 && *s) {
if (0xf0 <= *(guchar*)s && *(guchar*)s <= 0xfd) offset--;
s = g_utf8_next_char (s);
r++;
}
return r;
}
glong g_utf8_offset_to_utf16_offset(const gchar* str, glong offset) {
glong r = 0;
const gchar *s = str;
if (!s) return 0;
while (offset-- > 0 && *s) {
if (0xf0 <= *(guchar*)s && *(guchar*)s <= 0xfd) r++;
s = g_utf8_next_char (s);
r++;
}
return r;
}
#ifndef NO_SwtFixed
struct _SwtFixedPrivate {
GtkAdjustment *hadjustment;
GtkAdjustment *vadjustment;
guint hscroll_policy : 1;
guint vscroll_policy : 1;
GList *children;
};
struct _SwtFixedChild
{
GtkWidget *widget;
gint x;
gint y;
gint width;
gint height;
};
typedef struct _SwtFixedChild SwtFixedChild;
enum {
PROP_0,
PROP_HADJUSTMENT,
PROP_VADJUSTMENT,
PROP_HSCROLL_POLICY,
PROP_VSCROLL_POLICY,
};
static void swt_fixed_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static void swt_fixed_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void swt_fixed_finalize (GObject *object);
static void swt_fixed_realize (GtkWidget *widget);
static void swt_fixed_map (GtkWidget *widget);
static void swt_fixed_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural);
static void swt_fixed_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural);
static void swt_fixed_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
static void swt_fixed_add (GtkContainer *container, GtkWidget *widget);
static void swt_fixed_remove (GtkContainer *container, GtkWidget *widget);
static void swt_fixed_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
G_DEFINE_TYPE_WITH_CODE (SwtFixed, swt_fixed, GTK_TYPE_CONTAINER, G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
static void swt_fixed_class_init (SwtFixedClass *class) {
GObjectClass *gobject_class = (GObjectClass*) class;
GtkWidgetClass *widget_class = (GtkWidgetClass*) class;
GtkContainerClass *container_class = (GtkContainerClass*) class;
/* GOject implementation */
gobject_class->set_property = swt_fixed_set_property;
gobject_class->get_property = swt_fixed_get_property;
gobject_class->finalize = swt_fixed_finalize;
/* Scrollable implemetation */
g_object_class_override_property (gobject_class, PROP_HADJUSTMENT, "hadjustment");
g_object_class_override_property (gobject_class, PROP_VADJUSTMENT, "vadjustment");
g_object_class_override_property (gobject_class, PROP_HSCROLL_POLICY, "hscroll-policy");
g_object_class_override_property (gobject_class, PROP_VSCROLL_POLICY, "vscroll-policy");
/* Widget implementation */
widget_class->realize = swt_fixed_realize;
widget_class->map = swt_fixed_map;
widget_class->get_preferred_width = swt_fixed_get_preferred_width;
widget_class->get_preferred_height = swt_fixed_get_preferred_height;
widget_class->size_allocate = swt_fixed_size_allocate;
/* Container implementation */
container_class->add = swt_fixed_add;
container_class->remove = swt_fixed_remove;
container_class->forall = swt_fixed_forall;
g_type_class_add_private (class, sizeof (SwtFixedPrivate));
}
void swt_fixed_restack (SwtFixed *fixed, GtkWidget *widget, GtkWidget *sibling, gboolean above) {
SwtFixedPrivate *priv = fixed->priv;
GList *list;
SwtFixedChild *child, *sibling_child;
list = priv->children;
while (list) {
child = list->data;
if (child->widget == widget) break;
list = list->next;
}
if (!list) return;
priv->children = g_list_remove_link (priv->children, list);
g_list_free_1 (list);
list = NULL;
if (sibling) {
list = priv->children;
while (list) {
sibling_child = list->data;
if (sibling_child->widget == sibling) {
break;
}
list = list->next;
}
if (list) {
if (!above) list = list->next;
}
}
if (!list) {
list = above ? priv->children : NULL;
}
priv->children = g_list_insert_before (priv->children, list, child);
/*
{
GdkWindow *sibling_window = NULL;
if (list) {
child = list->data;
sibling_window = gtk_widget_get_window (child);
}
gdk_window_restack (gtk_widget_get_window (widget), sibling_window, above);
}
*/
}
static void swt_fixed_init (SwtFixed *widget) {
SwtFixedPrivate *priv;
priv = widget->priv = G_TYPE_INSTANCE_GET_PRIVATE (widget, SWT_TYPE_FIXED, SwtFixedPrivate);
priv->children = NULL;
priv->hadjustment = NULL;
priv->vadjustment = NULL;
}
static void swt_fixed_finalize (GObject *object) {
SwtFixed *widget = SWT_FIXED (object);
SwtFixedPrivate *priv = widget->priv;
g_object_unref (priv->hadjustment);
g_object_unref (priv->vadjustment);
G_OBJECT_CLASS (swt_fixed_parent_class)->finalize (object);
}
static void swt_fixed_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
SwtFixed *widget = SWT_FIXED (object);
SwtFixedPrivate *priv = widget->priv;
switch (prop_id) {
case PROP_HADJUSTMENT:
g_value_set_object (value, priv->hadjustment);
break;
case PROP_VADJUSTMENT:
g_value_set_object (value, priv->vadjustment);
break;
case PROP_HSCROLL_POLICY:
g_value_set_enum (value, priv->hscroll_policy);
break;
case PROP_VSCROLL_POLICY:
g_value_set_enum (value, priv->vscroll_policy);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void swt_fixed_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
SwtFixed *widget = SWT_FIXED (object);
SwtFixedPrivate *priv = widget->priv;
GtkAdjustment *adjustment;
switch (prop_id) {
case PROP_HADJUSTMENT:
adjustment = g_value_get_object (value);
if (adjustment && priv->hadjustment == adjustment) return;
if (priv->hadjustment != NULL) g_object_unref (priv->hadjustment);
if (adjustment == NULL) adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
priv->hadjustment = g_object_ref_sink (adjustment);
g_object_notify (G_OBJECT (widget), "hadjustment");
break;
case PROP_VADJUSTMENT:
adjustment = g_value_get_object (value);
if (adjustment && priv->vadjustment == adjustment) return;
if (priv->vadjustment != NULL) g_object_unref (priv->vadjustment);
if (adjustment == NULL) adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
priv->vadjustment = g_object_ref_sink (adjustment);
g_object_notify (G_OBJECT (widget), "vadjustment");
break;
case PROP_HSCROLL_POLICY:
priv->hscroll_policy = g_value_get_enum (value);
break;
case PROP_VSCROLL_POLICY:
priv->vscroll_policy = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void swt_fixed_realize (GtkWidget *widget) {
GtkAllocation allocation;
GdkWindow *window;
GdkWindowAttr attributes;
gint attributes_mask;
if (!gtk_widget_get_has_window (widget)) {
GTK_WIDGET_CLASS (swt_fixed_parent_class)->realize (widget);
return;
}
gtk_widget_set_realized (widget, TRUE);
gtk_widget_get_allocation (widget, &allocation);
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = allocation.x;
attributes.y = allocation.y;
attributes.width = allocation.width;
attributes.height = allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gtk_widget_get_visual (widget);
attributes.event_mask = GDK_EXPOSURE_MASK | GDK_SCROLL_MASK | 1 << 23 /*GDK_SMOOTH_SCROLL_MASK*/ | gtk_widget_get_events (widget);
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
gtk_widget_set_window (widget, window);
gdk_window_set_user_data (window, widget);
if (NULL != gtk_check_version (3, 18, 0)) {
gtk_style_context_set_background (gtk_widget_get_style_context (widget), window);
}
}
static void swt_fixed_map (GtkWidget *widget) {
SwtFixed *fixed = SWT_FIXED (widget);
SwtFixedPrivate *priv = fixed->priv;
GList *list;
gtk_widget_set_mapped (widget, TRUE);
list = priv->children;
while (list) {
SwtFixedChild *child_data = list->data;
GtkWidget *child = child_data->widget;
list = list->next;
if (gtk_widget_get_visible (child)) {
if (!gtk_widget_get_mapped (child)) gtk_widget_map (child);
}
}
if (gtk_widget_get_has_window (widget)) {
//NOTE: contrary to most of GTK, swt_fixed_* container does not raise windows upon showing them.
//This has the effect that widgets are drawn *beneath* the previous one.
//E.g if this line is changed to gdk_window_show (..) then widgets are drawn on top of the previous one.
//This affects mostly only the absolute layout with overlapping widgets, e.g minimizied panels that
//pop-out in Eclipse (aka fast-view).
//As such, be attentive to swt_fixed_forall(..); traversing children may need to be done in reverse in some
//cases.
gdk_window_show_unraised (gtk_widget_get_window (widget));
}
}
static void swt_fixed_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural) {
if (minimum) *minimum = 0;
if (natural) *natural = 0;
}
static void swt_fixed_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural) {
if (minimum) *minimum = 0;
if (natural) *natural = 0;
}
static void swt_fixed_size_allocate (GtkWidget *widget, GtkAllocation *allocation) {
SwtFixed *fixed = SWT_FIXED (widget);
SwtFixedPrivate *priv = fixed->priv;
GList *list;
GtkAllocation child_allocation;
GtkRequisition requisition;
gint w, h;
gtk_widget_set_allocation (widget, allocation);
if (gtk_widget_get_has_window (widget)) {
if (gtk_widget_get_realized (widget)) {
gdk_window_move_resize (gtk_widget_get_window (widget), allocation->x, allocation->y, allocation->width, allocation->height);
}
}
list = priv->children;
while (list) {
SwtFixedChild *child_data = list->data;
GtkWidget *child = child_data->widget;
list = list->next;
child_allocation.x = child_data->x;
child_allocation.y = child_data->y;
if (!gtk_widget_get_has_window (widget)) {
child_allocation.x += allocation->x;
child_allocation.y += allocation->y;
}
w = child_data->width;
h = child_data->height;
if (w == -1 || h == -1) {
gtk_widget_get_preferred_size (child, &requisition, NULL);
if (w == -1) w = requisition.width;
if (h == -1) h = requisition.height;
}
// Feature in GTK: gtk_widget_preferred_size() has to be called before
// gtk_widget_size_allocate otherwise a warning is thrown. See Bug 486068.
gtk_widget_get_preferred_size (child, &requisition, NULL);
child_allocation.width = w;
child_allocation.height = h;
gtk_widget_size_allocate (child, &child_allocation);
}
}
void swt_fixed_move (SwtFixed *fixed, GtkWidget *widget, gint x, gint y) {
SwtFixedPrivate *priv = fixed->priv;
GList *list;
list = priv->children;
while (list) {
SwtFixedChild *child_data = list->data;
GtkWidget *child = child_data->widget;
if (child == widget) {
child_data->x = x;
child_data->y = y;
break;
}
list = list->next;
}
}
void swt_fixed_resize (SwtFixed *fixed, GtkWidget *widget, gint width, gint height) {
SwtFixedPrivate *priv = fixed->priv;
GList *list;
list = priv->children;
while (list) {
SwtFixedChild *child_data = list->data;
GtkWidget *child = child_data->widget;
if (child == widget) {
child_data->width = width;
child_data->height = height;
break;
}
list = list->next;
}
}
static void swt_fixed_add (GtkContainer *container, GtkWidget *child) {
GtkWidget *widget = GTK_WIDGET (container);
SwtFixed *fixed = SWT_FIXED (container);
SwtFixedPrivate *priv = fixed->priv;
SwtFixedChild *child_data;
child_data = g_new (SwtFixedChild, 1);
child_data->widget = child;
child_data->x = child_data->y = 0;
child_data->width = child_data->height = -1;
priv->children = g_list_append (priv->children, child_data);
gtk_widget_set_parent (child, widget);
}
static void swt_fixed_remove (GtkContainer *container, GtkWidget *widget) {
SwtFixed *fixed = SWT_FIXED (container);
SwtFixedPrivate *priv = fixed->priv;
GList *list;
list = priv->children;
while (list) {
SwtFixedChild *child_data = list->data;
GtkWidget *child = child_data->widget;
if (child == widget) {
gtk_widget_unparent (widget);
priv->children = g_list_remove_link (priv->children, list);
g_list_free_1 (list);
g_free (child_data);
break;
}
list = list->next;
}
}
static void swt_fixed_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data) {
SwtFixed *fixed = SWT_FIXED (container);
SwtFixedPrivate *priv = fixed->priv;
GList *list;
list = priv->children;
// NOTE: The direction of the list traversal is conditional.
//
// 1) When we do a *_foreach() traversal (i.e, include_internals==FALSE), we traverse the list as normal
// from front to back.
// This is used to layout higher level widgets inside containers (e.g row/grid etc..) in the expected way.
// If for a non-internal traversal we were to go in reverse, then widgets would get laid out in inverse order.
// 2) When we do a *_forall() traversal (i.e, include_internals==TRUE), we traverse the list in *reverse* order.
// This is an internal traversal of the internals of a widget. Reverse traversal is necessary for things like
// DnD Drop and DnD Motion events to find the correct widget in the case of overlapping widgets on an absolute layout.
// Reversal is required because in swt_fixed_map(..) we do not raise the widget when we show it, as a result
// the stack is in reverse.
if (include_internals)
list = g_list_last(list);
while (list) {
SwtFixedChild *child_data = list->data;
GtkWidget *child = child_data->widget;
if (include_internals)
list = list->prev;
else
list = list->next;
(* callback) (child, callback_data);
}
}
#endif
//Add ability to debug gtk warnings for SWT snippets via SWT_FATAL_WARNINGS=1
// env variable. Please see Eclipse bug 471477
void swt_debug_on_fatal_warnings() {
// NOTE: gtk_parse_args() must be called before gtk_init() to take effect.
int argcount = 2;
char *argument[] = {"", "--g-fatal-warnings"};
char **arg2 = (char **) &argument;
gtk_parse_args(&argcount, &arg2);
}