diff --git a/src/post_modules/GTK2/Makefile.in b/src/post_modules/GTK2/Makefile.in index 7ba387033eee8ec0cbf87b2c2fd47d5b5abe4901..ee768c165314cb22ce980bcc8b2f40fe237eff23 100644 --- a/src/post_modules/GTK2/Makefile.in +++ b/src/post_modules/GTK2/Makefile.in @@ -51,9 +51,9 @@ compile1: done; \ else :; fi @echo "Original CFLAGS:$(CFLAGS)" - @echo "Modified CFLAGS:`echo ' $(CFLAGS) ' | sed -e 's/ -g[^ ]*//g' -e 's/ -W[^ ]*//g'` `echo ' $(CFLAGS) ' | sed -ne 's/.*\( -gcc-version[^ ]*\).*/\1/p'`" + @echo "Modified CFLAGS:`echo $(CFLAGS) | sed -e 's/-g[^ ]*//g' -e 's/-W[^ ]*//g'`" @$(MAKE) OBJS="`cat files_to_compile`" \ - CFLAGS="`echo ' $(CFLAGS) ' | sed -e 's/ -g[^ ]*/ /g' -e 's/ -W[^ ]*/ /g'` `echo ' $(CFLAGS) ' | sed -ne 's/.*\( -gcc-version[^ ]*\).*/\1/p'`" \ + CFLAGS="`echo $(CFLAGS) | sed -e 's/ -g[^ ]*/ /g' -e 's/ -W[^ ]*/ /g'`" \ all compile2: compile1 diff --git a/src/post_modules/GTK2/acconfig.h b/src/post_modules/GTK2/acconfig.h index 5d3bf21a7947e7a8efb451a0dbc58a10c621ede4..88b4e5ffdc54f5bb53472bdabb98eb74138ae7bf 100644 --- a/src/post_modules/GTK2/acconfig.h +++ b/src/post_modules/GTK2/acconfig.h @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: acconfig.h,v 1.7 2005/11/07 17:25:11 grubba Exp $ +|| $Id: acconfig.h,v 1.8 2006/08/02 13:42:31 ldillon Exp $ */ #undef FUNCPROTO @@ -13,6 +13,7 @@ #undef HAVE_GTK24 #undef HAVE_GTK26 #undef HAVE_GTK28 +#undef HAVE_GTK210 #undef HAVE_ATK #undef HAVE_ATK18 #undef HAVE_PANGO diff --git a/src/post_modules/GTK2/pgtk.h b/src/post_modules/GTK2/pgtk.h index 53877e9c6da27f081af1767b9d1a3780d9e4baa8..f46fc64679d8f62f604688ff847a04dba2bb8fb6 100644 --- a/src/post_modules/GTK2/pgtk.h +++ b/src/post_modules/GTK2/pgtk.h @@ -2,11 +2,13 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: pgtk.h,v 1.14 2006/02/27 12:23:15 mast Exp $ +|| $Id: pgtk.h,v 1.15 2006/08/02 13:42:31 ldillon Exp $ */ /* Sort of unnessesary, and decreases code-size with 140Kb */ +/* #define GTK_NO_CHECK_CASTS +*/ /* Also sort of unessesary, most code is autogenerated anyway. */ #define NO_PIKE_SHORTHAND #include "pgtk_config.h" @@ -125,7 +127,12 @@ void pgtk2_push_Xpseudo32bitstring(void *f, int nelems); int pgtk2_get_color_from_pikecolor(struct object *o, INT_TYPE *r, INT_TYPE *g, INT_TYPE *b); #define get_color_from_pikecolor pgtk2_get_color_from_pikecolor -int pgtk2_signal_func_wrapper(struct signal_data *d, ...); +/*int pgtk2_signal_func_wrapper(struct signal_data *d, ...); */ +void pgtk2_signal_func_wrapper(struct signal_data *d, + gpointer go, + guint n_params, + const GValue *param_values, + GValue *return_value); void pgtk2_free_signal_data(struct signal_data *s, GClosure *gcl); void pgtk2_free_object(struct object *o); @@ -307,5 +314,20 @@ GObject *pgtk2_create_new_obj_with_properties(GType type, struct mapping *m); get_all_args("create",args,"%m",&m); \ THIS->obj=pgtk2_create_new_obj_with_properties(X,m); \ } while(0) -void pgtk2_push_gvalue_r(GValue *param, GType t); +void pgtk2_push_gvalue_r(const GValue *param, GType t); #define push_gvalue_r pgtk2_push_gvalue_r + +#ifdef HAVE_CAIRO +/* from picairo */ +#include <cairo.h> +struct cairo_mod_context { + cairo_t *ctx; +}; +#endif + +void pgtk2_marshaller(GClosure *closure, GValue *return_value, + guint n_param_values, const GValue *param_values, + gpointer invocation_hint, gpointer marshal_data); + +#define pgtk2_set_value(X,Y) pgtk2_set_gvalue((X),G_VALUE_TYPE(X),Y) +#define pgtk2_push_gvalue_rt(X) pgtk2_push_gvalue_r((X),G_VALUE_TYPE(X)) diff --git a/src/post_modules/GTK2/source/gobject.pre b/src/post_modules/GTK2/source/gobject.pre index c6f4dd161d637c8c9ec1e2ab71cdf79bcf9b906a..df29b343d2984b7c288ebc0615319105e758f664 100644 --- a/src/post_modules/GTK2/source/gobject.pre +++ b/src/post_modules/GTK2/source/gobject.pre @@ -42,7 +42,9 @@ mixed get_property(string property) } } + int signal_connect(string signal, function callback, mixed|void callback_arg) +//! int signal_connect(string signal, function callback, mixed ... args) //! Connect a signal to a pike function. The function will be called with //! the last argument to this function as it's first argument (defaults to 0), //! the second argument is always the widget, and any other arguments are the @@ -56,6 +58,7 @@ int signal_connect(string signal, function callback, mixed|void callback_arg) int id; struct signal_data *b; struct svalue *tmp1,*tmp2; + GClosure *gc; if (args==2) { push_int(0); @@ -72,22 +75,15 @@ int signal_connect(string signal, function callback, mixed|void callback_arg) b->signal_id=g_signal_lookup(a,G_TYPE_FROM_INSTANCE(THIS->obj)); if (!b->signal_id) { - xfree(b); + g_free(b); Pike_error("Signal \"%s\" is not defined in the '%s' class ancestry.\n", a,g_type_name(G_TYPE_FROM_INSTANCE(THIS->obj))); } - - id=g_signal_connect_data(G_OBJECT(THIS->obj),a, - G_CALLBACK(pgtk2_signal_func_wrapper), - b, - (GClosureNotify)pgtk2_free_signal_data, -#ifdef HAVE_G_SIGNAL_CONNECT_DATA_WITH_SIX_ARGS - G_CONNECT_SWAPPED -#else /* !HAVE_G_SIGNAL_CONNECT_DATA_WITH_SIX_ARGS - /* Old-style. */ - 1 /* swapped */, 0 /* after */ -#endif /* !HAVE_G_SIGNAL_CONNECT_DATA_WITH_SIX_ARGS */ - ); + gc=g_cclosure_new_swap(G_CALLBACK(pgtk2_signal_func_wrapper), + b,(GClosureNotify)pgtk2_free_signal_data); + g_closure_set_marshal(gc,pgtk2_marshaller); + id=g_signal_connect_closure(G_OBJECT(THIS->obj),a, + gc,1); pgtk2_pop_n_elems(args); push_int(id); } @@ -126,10 +122,126 @@ void signal_unblock(int signal_id) void signal_emit(string signal_name) //! Send the current named signal. { - char *s; - get_all_args("signal_emit",args,"%s",&s); - g_signal_emit_by_name(G_OBJECT(THIS->obj),s,NULL); - RETURN_THIS(); + pgtk2_verify_inited(); + { + char *s; + GQuark gq; + GSignalQuery _opts; + GSignalQuery *opts=&_opts; + guint signal_id; + + get_all_args("signal_emit",args,"%s",&s); + gq=g_quark_from_string(s); + signal_id=g_signal_lookup(s,G_TYPE_FROM_INSTANCE(THIS->obj)); + g_signal_query(signal_id,opts); + if (opts->n_params!=args-1) { + pgtk2_pop_n_elems(args); +/* Pike_error("Signal %s expects %d args, got %d.\n",s,opts->n_params,args-1); */ + Pike_error("signal_emit: signature mismatch for signal \"%s\" in the '%s' class ancestry.\n" + " expected %d args, got %d.\n",s, + g_type_name(G_OBJECT_TYPE(THIS->obj)),opts->n_params,args-1); + } + { + int i; + GValue params[opts->n_params+1]; + GValue rvalue={0, }; + + memset(params,0,sizeof(GValue)*(opts->n_params+1)); + g_value_init(params+0,G_TYPE_FROM_INSTANCE(THIS->obj)); + g_value_set_object(params+0,G_OBJECT(THIS->obj)); + for (i=0; i<opts->n_params; i++) { + pgtk2_set_gvalue(params+i+1,opts->param_types[i],&Pike_sp[-args+(i+1)]); + } + if (opts->return_type!=G_TYPE_NONE) + g_value_init(&rvalue,opts->return_type); + g_signal_emitv(params,signal_id,0,&rvalue); + pgtk2_pop_n_elems(args); + if (opts->return_type!=G_TYPE_NONE) { + pgtk2_push_gvalue_rt(&rvalue); + } else { + push_int(0); + } + g_value_unset(params); + for (i=1; i<opts->n_params; i++) + g_value_unset(params+i); + } + } +} + +int new_signal(string name, array types, string return_type) +//! Create a new signal. +{ + pgtk2_verify_inited(); + { + struct pike_string *t; + char *ret_type_name; + struct array *a; + GObject *go; + gchar *name; + guint id; + GType *param_types; + guint n_params; + GType return_type; + struct signal_data *b; + int i; + + get_all_args("new_signal",args,"%T%A%s",&t,&a,&ret_type_name); + if (a->size) { + ref_push_string(t); + f_string_to_utf8(1); + name=g_strdup(CGSTR0(Pike_sp[-1].u.string)); + if (name==NULL) { + pop_stack(); + SIMPLE_OUT_OF_MEMORY_ERROR("new_signal",strlen(ret_type_name)*2); + } + if (!strcmp(ret_type_name,"void")) { + return_type=G_TYPE_NONE; + } else if (!strcmp(ret_type_name,"int")) { + return_type=G_TYPE_INT; + } else if (!strcmp(ret_type_name,"float")) { + return_type=G_TYPE_DOUBLE; + } else if (!strcmp(ret_type_name,"string")) { + return_type=G_TYPE_STRING; + } else if (!strcmp(ret_type_name,"object")) { + return_type=G_TYPE_OBJECT; + } else { + return_type=G_TYPE_POINTER; + } + param_types=xmalloc(sizeof(GType)*a->size); + if (param_types==NULL) { + g_free(name); + SIMPLE_OUT_OF_MEMORY_ERROR("new_signal",sizeof(GType)*a->size); + } + for (i=n_params=0; i<a->size; i++) { + if (ITEM(a)[i].type!=PIKE_T_STRING) + continue; + if (!strcmp(CGSTR0(ITEM(a)[i].u.string),"int")) { + param_types[n_params]=G_TYPE_INT; + n_params++; + } else if (!strcmp(CGSTR0(ITEM(a)[i].u.string),"float")) { + param_types[n_params]=G_TYPE_DOUBLE; + n_params++; + } else if (!strcmp(CGSTR0(ITEM(a)[i].u.string),"string")) { + param_types[n_params]=G_TYPE_STRING; + n_params++; + } else if (!strcmp(CGSTR0(ITEM(a)[i].u.string),"object")) { + param_types[n_params]=G_TYPE_OBJECT; + n_params++; + } else { + param_types[n_params]=G_TYPE_POINTER; + n_params++; + } + + } + pgtk2_pop_n_elems(args); + id=g_signal_newv(name,G_TYPE_FROM_INSTANCE(THIS->obj),G_SIGNAL_RUN_LAST, + NULL,NULL,NULL,pgtk2_marshaller,return_type, + n_params,param_types); + push_int(id); + xfree(param_types); + g_free(name); + } + } } void notify(string property); @@ -149,4 +261,13 @@ void accel_groups_activate(int accel_key, int accel_mods) RETURN_THIS(); } +require gtk210; +/* +object ref_sink(); +//! Increase the reference count of this object, and possibly remove the +//! floating reference, if this object has a floating reference. +*/ +int is_floating(); +//! Checks whether this object has a floating reference. +endrequire; diff --git a/src/post_modules/GTK2/source/support.c b/src/post_modules/GTK2/source/support.c index 85b0d13287dc457522e6200a630b7ad4469da97e..bb6b566d3390698e1793a9698aa6b877ab364f9d 100644 --- a/src/post_modules/GTK2/source/support.c +++ b/src/post_modules/GTK2/source/support.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: support.c,v 1.11 2006/02/27 12:23:18 mast Exp $ +|| $Id: support.c,v 1.12 2006/08/02 13:42:31 ldillon Exp $ */ #include <version.h> @@ -474,31 +474,31 @@ static int pgtk2_push_selection_data_param( GValue *a ) } */ -static int pgtk2_push_accel_group_param(GValue *a) { +static int pgtk2_push_accel_group_param(const GValue *a) { g_object_ref(g_value_get_pointer(a)); push_gobjectclass(g_value_get_pointer(a),pgtk2_accel_group_program); return PUSHED_VALUE; } /* -static int pgtk2_push_ctree_node_param( GValue *a ) +static int pgtk2_push_ctree_node_param(const GValue *a ) { push_pgdk2object( GTK_VALUE_POINTER(*a), pgtk2_ctree_node_program); return PUSHED_VALUE; } */ -static int pgtk2_push_gdk_drag_context_param(GValue *a) { +static int pgtk2_push_gdk_drag_context_param(const GValue *a) { push_gdkobject(g_value_get_pointer(a),drag_context); return PUSHED_VALUE; } -static int pgtk2_push_gdk_event_param(GValue *a) { +static int pgtk2_push_gdk_event_param(const GValue *a) { push_gdk_event(g_value_get_boxed(a)); return NEED_RETURN; } -static int pgtk2_push_gdk_rectangle_param(GValue *a) { +static int pgtk2_push_gdk_rectangle_param(const GValue *a) { GdkRectangle *r = (GdkRectangle *) g_value_get_boxed(a); push_text("x"); push_int(r->x); push_text("y"); push_int(r->y); @@ -508,7 +508,7 @@ static int pgtk2_push_gdk_rectangle_param(GValue *a) { return PUSHED_VALUE; } -static int pgtk2_push_int_param(GValue *a) { +static int pgtk2_push_int_param(const GValue *a) { LONGEST retval; switch (G_VALUE_TYPE(a)) { case G_TYPE_INT: @@ -537,7 +537,7 @@ static int pgtk2_push_int_param(GValue *a) { return PUSHED_VALUE; } -static int pgtk2_push_float_param(GValue *a) { +static int pgtk2_push_float_param(const GValue *a) { FLOAT_TYPE retval; if (G_VALUE_TYPE(a)==G_TYPE_FLOAT) retval=(FLOAT_TYPE)g_value_get_float(a); @@ -547,7 +547,7 @@ static int pgtk2_push_float_param(GValue *a) { return PUSHED_VALUE; } -static int pgtk2_push_string_param(GValue *a) { +static int pgtk2_push_string_param(const GValue *a) { const gchar *t=g_value_get_string(a); if (t) PGTK_PUSH_GCHAR(t); @@ -556,32 +556,33 @@ static int pgtk2_push_string_param(GValue *a) { return PUSHED_VALUE; } -static int pgtk2_push_object_param(GValue *a) { +static int pgtk2_push_object_param(const GValue *a) { GObject *obj=g_value_get_object(a); if (obj) - push_gobject(((void *)g_value_get_object(a))); +/* push_gobject(((void *)g_value_get_object(a))); */ + push_gobject(obj); return PUSHED_VALUE; } -static int pgtk2_push_pike_object_param(GValue *a) { +static int pgtk2_push_pike_object_param(const GValue *a) { struct object *o=g_value_get_pointer(a); if (o) ref_push_object(o); return PUSHED_VALUE; } -static int pgtk2_push_gparamspec_param(GValue *a) { +static int pgtk2_push_gparamspec_param(const GValue *a) { } static struct push_callback { - int (*callback)(GValue *); + int (*callback)(const GValue *); GType id; struct push_callback *next; } push_callbacks[100], *push_cbtable[63]; static int last_used_callback = 0; -static void insert_push_callback(GType i, int (*cb)(GValue *)) { +static void insert_push_callback(GType i, int (*cb)(const GValue *)) { struct push_callback *new=push_callbacks+last_used_callback++; struct push_callback *old=push_cbtable[i%63]; new->id=i; @@ -639,7 +640,7 @@ static void build_push_callbacks() { * This might not be exactly what we want */ } -void push_gvalue_r(GValue *param, GType t) { +void push_gvalue_r(const GValue *param, GType t) { int i; struct push_callback *cb=push_cbtable[t%63]; @@ -681,50 +682,33 @@ void push_gvalue_r(GValue *param, GType t) { * params[nparams] should be set to the return value. It does seem to work, * though. */ -int pgtk2_signal_func_wrapper(struct signal_data *d, ...) { - int i,return_value=0,j; - struct svalue *osp=Pike_sp; - GSignalQuery _opts; - GSignalQuery *opts=&_opts; - va_list ptr; +/* This function is implement by the functions in the gobject api */ +void pgtk2_signal_func_wrapper(struct signal_data *d, + gpointer go, + guint n_params, + const GValue *param_values, + GValue *return_value) { + int i; if (!last_used_callback) build_push_callbacks(); - g_signal_query(d->signal_id,opts); - va_start(ptr,d); - for (i=j=0; i<opts->n_params; i++) { - GValue v= {0, }; - gchar *error=NULL; - g_value_init(&v,opts->param_types[i]); - G_VALUE_COLLECT(&v,ptr,G_VALUE_NOCOPY_CONTENTS,&error); - if (error) { - g_free(error); - continue; - } - push_gvalue_r(&v,opts->param_types[i]); - j++; - } - if (j /*opts->n_params*/) - f_aggregate(j /*opts->n_params*/); - { - GObject *obj=va_arg(ptr,GObject *); - push_gobject(obj); + push_gobject(G_OBJECT(go)); + for (i=0; i<n_params; i++) { + pgtk2_push_gvalue_rt(&(param_values[i])); } - va_end(ptr); - - if (j /*opts->n_params*/) - stack_swap(); + if (n_params) + f_aggregate(n_params); push_svalue(&d->args); - if (j /*opts->n_params*/) + if (n_params) apply_svalue(&d->cb,3); else apply_svalue(&d->cb,2); - return_value=Pike_sp[-1].u.integer; - pop_stack(); - return return_value; + if (return_value) { + pgtk2_set_value(return_value,&Pike_sp[-1]); + pop_stack(); + } } - void pgtk2_free_signal_data(struct signal_data *s, GClosure *gcl) { free_svalue(&s->cb); free_svalue(&s->args); @@ -1069,8 +1053,11 @@ void pgtk2_destroy_store_data(gpointer data) { g_free(sd); } + + void pgtk2_set_gvalue(GValue *gv, GType gt, struct svalue *sv) { - g_value_init(gv,gt); + if (!G_IS_VALUE(gv)) + g_value_init(gv,gt); if (G_TYPE_IS_ENUM(gt)) { g_value_set_enum(gv,(gint)PGTK_GETINT(sv)); return; @@ -1142,9 +1129,10 @@ void pgtk2_set_gvalue(GValue *gv, GType gt, struct svalue *sv) { g_value_set_double(gv,(gdouble)pgtk2_get_float(sv)); break; case G_TYPE_STRING: - if (sv->type==PIKE_T_STRING) - g_value_set_string(gv,GSTR0(sv->u.string)); - else + if (sv->type==PIKE_T_STRING) { + g_value_set_string(gv,CGSTR0(sv->u.string)); + add_ref(sv->u.string); + } else g_value_set_string(gv,""); break; case G_TYPE_OBJECT: @@ -1218,3 +1206,30 @@ GObject *pgtk2_create_new_obj_with_properties(GType type, struct mapping *m) { g_type_class_unref(class); return obj; } + +void pgtk2_marshaller(GClosure *closure, + GValue *return_value, + guint n_params, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) { + typedef void (*pgtk2_marshal_func)(gpointer data1, + gpointer data2, + guint n_params, + const GValue *param_values, + GValue *return_value); + register pgtk2_marshal_func callback; + register GCClosure *cc=(GCClosure *)closure; + register gpointer data1,data2; + + + if (G_CCLOSURE_SWAP_DATA(closure)) { + data1=closure->data; + data2=g_value_peek_pointer(param_values+0); + } else { + data1=g_value_peek_pointer(param_values+0); + data2=closure->data; + } + callback=(pgtk2_marshal_func)(marshal_data?marshal_data:cc->callback); + callback(data1,data2,n_params-1,param_values+1,return_value); +}