@@ -9,6 +9,7 @@ use types::{self, StaticType};
99use wrapper:: { UnsafeFrom , Wrapper } ;
1010use gobject_ffi;
1111use std:: mem;
12+ use std:: ptr;
1213
1314use Value ;
1415use Type ;
@@ -355,6 +356,7 @@ pub trait ObjectExt {
355356
356357 fn connect < ' a , N , F > ( & self , signal_name : N , after : bool , callback : F ) -> Result < u64 , BoolError >
357358 where N : Into < & ' a str > , F : Fn ( & [ Value ] ) -> Option < Value > + Send + Sync + ' static ;
359+ fn emit < ' a , N : Into < & ' a str > > ( & self , signal_name : N , args : & [ & Value ] ) -> Result < Option < Value > , BoolError > ;
358360}
359361
360362fn get_property_type < T : IsA < Object > > ( obj : & T , property_name : & str ) -> Option < Type > {
@@ -486,4 +488,59 @@ impl<T: IsA<Object>> ObjectExt for T {
486488 }
487489 }
488490 }
491+
492+ fn emit < ' a , N : Into < & ' a str > > ( & self , signal_name : N , args : & [ & Value ] ) -> Result < Option < Value > , BoolError > {
493+ let signal_name: & str = signal_name. into ( ) ;
494+ unsafe {
495+ let type_ = self . get_type ( ) ;
496+
497+ let mut signal_id = 0 ;
498+ let mut signal_detail = 0 ;
499+
500+ let found: bool = from_glib ( gobject_ffi:: g_signal_parse_name ( signal_name. to_glib_none ( ) . 0 ,
501+ type_. to_glib ( ) , & mut signal_id,
502+ & mut signal_detail, true . to_glib ( ) ) ) ;
503+
504+ if !found {
505+ return Err ( BoolError ( "Signal not found" ) ) ;
506+ }
507+
508+ let mut details = mem:: zeroed ( ) ;
509+ gobject_ffi:: g_signal_query ( signal_id, & mut details) ;
510+ if details. signal_id != signal_id {
511+ return Err ( BoolError ( "Signal not found" ) ) ;
512+ }
513+
514+ if details. n_params != args. len ( ) as u32 {
515+ return Err ( BoolError ( "Incompatible number of arguments" ) ) ;
516+ }
517+
518+ for i in 0 ..details. n_params {
519+ let arg_type = * ( details. param_types . offset ( i as isize ) ) & ( !gobject_ffi:: G_TYPE_FLAG_RESERVED_ID_BIT ) ;
520+ if arg_type != args[ i as usize ] . type_ ( ) . to_glib ( ) {
521+ return Err ( BoolError ( "Incompatible argument types" ) ) ;
522+ }
523+ }
524+
525+ let mut c_args: Vec < gobject_ffi:: GValue > = Vec :: new ( ) ;
526+ let instance = Value :: from ( self ) ;
527+ c_args. push ( ptr:: read ( instance. to_glib_none ( ) . 0 ) ) ;
528+ for arg in args {
529+ c_args. push ( ptr:: read ( arg. to_glib_none ( ) . 0 ) ) ;
530+ }
531+
532+ let mut return_value = Value :: uninitialized ( ) ;
533+ if details. return_type != gobject_ffi:: G_TYPE_NONE {
534+ gobject_ffi:: g_value_init ( return_value. to_glib_none_mut ( ) . 0 , details. return_type ) ;
535+ }
536+
537+ gobject_ffi:: g_signal_emitv ( mut_override ( c_args. as_ptr ( ) ) , signal_id, signal_detail, return_value. to_glib_none_mut ( ) . 0 ) ;
538+
539+ if return_value. type_ ( ) != Type :: Unit && return_value. type_ ( ) != Type :: Invalid {
540+ Ok ( Some ( return_value) )
541+ } else {
542+ Ok ( None )
543+ }
544+ }
545+ }
489546}
0 commit comments