Glib

 view release on metacpan or  search on metacpan

GSignal.xs  view on Meta::CPAN

MODULE = Glib::Signal	PACKAGE = Glib::Object	PREFIX = g_

##
##/* --- typedefs --- */
##typedef struct _GSignalQuery		 GSignalQuery;
##typedef struct _GSignalInvocationHint	 GSignalInvocationHint;
##typedef GClosureMarshal			 GSignalCMarshaller;
##typedef gboolean (*GSignalEmissionHook) (GSignalInvocationHint *ihint,
##					 guint			n_param_values,
##					 const GValue	       *param_values,
##					 gpointer		data);
##typedef gboolean (*GSignalAccumulator)	(GSignalInvocationHint *ihint,
##					 GValue		       *return_accu,
##					 const GValue	       *handler_return,
##					 gpointer               data);


###
### ## creating signals ##
### new signals are currently created as a byproduct of Glib::Type::register
###
##        g_signal_newv
##        g_signal_new_valist
##        g_signal_new

###
### ## emitting signals ##
### all versions of g_signal_emit go through Glib::Object::signal_emit,
### which is mostly equivalent to g_signal_emit_by_name.
###
##        g_signal_emitv
##        g_signal_emit_valist
##        g_signal_emit
##        g_signal_emit_by_name

## heavily borrowed from gtk-perl and goran's code in gtk2-perl, which
## was inspired by pygtk's pyobject.c::pygobject_emit

=for apidoc

=for signature retval = $object->signal_emit ($name, ...)

=for arg name (string) the name of the signal

=for arg ... (list) any arguments to pass to handlers.

Emit the signal I<name> on I<$object>.  The number and types of additional
arguments in I<...> are determined by the signal; similarly, the presence
and type of return value depends on the signal being emitted.

=cut
void
g_signal_emit (instance, name, ...)
	GObject * instance
	char * name
    PREINIT:
	guint signal_id, i;
	GQuark detail;
	GSignalQuery query;
	GValue * params;
    PPCODE:
#define ARGOFFSET 2
	signal_id = parse_signal_name_or_croak
				(name, G_OBJECT_TYPE (instance), &detail);

	g_signal_query (signal_id, &query);

	if (((guint)(items-ARGOFFSET)) != query.n_params) 
		croak ("Incorrect number of arguments for emission of signal %s in class %s; need %d but got %d",
		       name, G_OBJECT_TYPE_NAME (instance),
		       query.n_params, (gint) items-ARGOFFSET);

	/* set up the parameters to g_signal_emitv.   this is an array
	 * of GValues, where [0] is the emission instance, and the rest 
	 * are the query.n_params arguments. */
	params = g_new0 (GValue, query.n_params + 1);

	g_value_init (&params[0], G_OBJECT_TYPE (instance));
	g_value_set_object (&params[0], instance);

	for (i = 0 ; i < query.n_params ; i++) {
		g_value_init (&params[i+1], 
			      query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE);
		if (!gperl_value_from_sv (&params[i+1], ST (ARGOFFSET+i)))
			croak ("Couldn't convert value %s to type %s for parameter %d of signal %s on a %s",
			       SvPV_nolen (ST (ARGOFFSET+i)),
			       g_type_name (G_VALUE_TYPE (&params[i+1])),
			       i, name, G_OBJECT_TYPE_NAME (instance));
	}

	/* now actually call it.  what we do depends on the return type of
	 * the signal; if the signal returns anything we need to capture it
	 * and push it onto the return stack. */
	if (query.return_type != G_TYPE_NONE) {
		/* signal returns a value, woohoo! */
		GValue ret = {0,};
		g_value_init (&ret, query.return_type);
		g_signal_emitv (params, signal_id, detail, &ret);
		EXTEND (SP, 1);
		SAVED_STACK_PUSHs (sv_2mortal (gperl_sv_from_value (&ret)));
		g_value_unset (&ret);
	} else {
		g_signal_emitv (params, signal_id, detail, NULL);
	}

	/* clean up */
	for (i = 0 ; i < query.n_params + 1 ; i++)
		g_value_unset (&params[i]);
	g_free (params);
#undef ARGOFFSET


##guint                 g_signal_lookup       (const gchar        *name,
##					     GType               itype);
##G_CONST_RETURN gchar* g_signal_name         (guint               signal_id);

##void g_signal_query (guint signal_id, GSignalQuery *query);
=for apidoc
Look up information about the signal I<$name> on the instance type
I<$object_or_class_name>, which may be either a Glib::Object or a package
name.

GSignal.xs  view on Meta::CPAN

=for arg data (scalar) data to match, ignored if undef
=cut

=for apidoc
=for arg func (subroutine) function to block
=for arg data (scalar) data to match, ignored if undef
=cut
int
signal_handlers_block_by_func (instance, func, data=NULL)
	GObject * instance
	SV * func
	SV * data
    ALIAS:
	Glib::Object::signal_handlers_unblock_by_func = 1
	Glib::Object::signal_handlers_disconnect_by_func = 2
    PREINIT:
	sig_match_callback callback = NULL;
    CODE:
	switch (ix) {
	    case 0: callback = g_signal_handlers_block_matched; break;
	    case 1: callback = g_signal_handlers_unblock_matched; break;
	    case 2: callback = g_signal_handlers_disconnect_matched; break;
	    default: g_assert_not_reached ();
	}
	RETVAL = foreach_closure_matched (instance, G_SIGNAL_MATCH_CLOSURE,
	                                  0, 0, func, data, callback);
    OUTPUT:
	RETVAL




##/* --- chaining for language bindings --- */
##void	g_signal_override_class_closure	      (guint		  signal_id,
##					       GType		  instance_type,
##					       GClosure		 *class_closure);
##void	g_signal_chain_from_overridden	      (const GValue      *instance_and_params,
##					       GValue            *return_value);
=for apidoc

Chain up to an overridden class closure; it is only valid to call this from
a class closure override.

Translation: because of various details in how GObjects are implemented,
the way to override a virtual method on a GObject is to provide a new "class
closure", or default handler for a signal.  This happens when a class is
registered with the type system (see Glib::Type::register and
L<Glib::Object::Subclass>).  When called from inside such an override, this
method runs the overridden class closure.  This is equivalent to calling
$self->SUPER::$method (@_) in normal Perl objects.

=cut
void
g_signal_chain_from_overridden (GObject * instance, ...)
    PREINIT:
	GSignalInvocationHint * ihint;
	GSignalQuery query;
	GValue * instance_and_params = NULL,
	         return_value = {0,};
	guint i;
    PPCODE:

	ihint = g_signal_get_invocation_hint (instance);
	if (!ihint)
		croak ("could not find signal invocation hint for %s(0x%p)",
		       G_OBJECT_TYPE_NAME (instance), instance);

	g_signal_query (ihint->signal_id, &query);

	if ((guint)items != 1 + query.n_params)
		croak ("incorrect number of parameters for signal %s, "
		       "expected %d, got %d",
		       g_signal_name (ihint->signal_id),
		       1 + query.n_params,
		       (gint) items);

	instance_and_params = g_new0 (GValue, 1 + query.n_params);

	g_value_init (&instance_and_params[0], G_OBJECT_TYPE (instance));
	g_value_set_object (&instance_and_params[0], instance);

	for (i = 0 ; i < query.n_params ; i++) {
		g_value_init (&instance_and_params[i+1],
		              query.param_types[i]
			         & ~G_SIGNAL_TYPE_STATIC_SCOPE);
		gperl_value_from_sv (&instance_and_params[i+1], ST (i+1));
	}

	if (query.return_type != G_TYPE_NONE)
		g_value_init (&return_value,
		              query.return_type
			         & ~G_SIGNAL_TYPE_STATIC_SCOPE);
	
	g_signal_chain_from_overridden (instance_and_params, &return_value);

	for (i = 0 ; i < 1 + query.n_params ; i++)
		g_value_unset (instance_and_params+i);
	g_free (instance_and_params);

	if (G_TYPE_NONE != (query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) {
		SAVED_STACK_XPUSHs (sv_2mortal (gperl_sv_from_value (&return_value)));
		g_value_unset (&return_value);
	}



( run in 1.096 second using v1.01-cache-2.11-cpan-5511b514fd6 )