From d80fb2adea70daf2e2de9ea2ac097c7436f8ae02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Derkacz?= Date: Wed, 21 Sep 2011 17:49:50 +0200 Subject: [PATCH] Improved signals handling --- glib_test.go | 12 ++++++------ object.go | 55 +++++++++++++++++++++++++++------------------------- signal.go | 12 +++++++++--- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/glib_test.go b/glib_test.go index fa0ca71..86ca416 100644 --- a/glib_test.go +++ b/glib_test.go @@ -42,31 +42,31 @@ func TestSignal(t *testing.T) { // Connect a.handler(*Object, int) to the signal. // o will be passed as its first argument. Second argument of type int will // be passed from second argument passed to the Emit function. - o.ConnectSid(s, (*A).handler, &a) + o.ConnectSid(s, 0, (*A).handler, &a) // Connect a.noiHandler(int) to the signal. // o will not be passed to the method. An argument of type int will be // passed from second argument passed to the Emit function. - o.ConnectSidNoi(s, (*A).noiHandler, &a) + o.ConnectSidNoi(s, 0, (*A).noiHandler, &a) // Connect funcHandler(*Object, int)to the signal. // o will be passed as its first argument. Second argument of type int // will be passed from second argument passed to the Emit function. - o.ConnectSid(s, funcHandler, nil) + o.ConnectSid(s, 0, funcHandler, nil) // Connect funcNoiHandler(int) to the signal. // o will not be passed to the function. An argument of type int will be // passed from second argument passed to the Emit function. - o.ConnectSidNoi(s, funcNoiHandler, nil) + o.ConnectSidNoi(s, 0, funcNoiHandler, nil) // Connect funcHandlerParam0(A, *Object, int) to the signal. // &a will be passed as its first argument, o will be passed as its second // argument. The thrid argument of type int will be from second argument // passed to the Emit function. - o.ConnectSid(s, funcHandlerParam0, &a) + o.ConnectSid(s, 0, funcHandlerParam0, &a) // Emit signal with 123 integer as argument. - o.EmitById(s, 123) + o.EmitById(s, 0, 123) } // Like TestSignal but uses signal names diff --git a/object.go b/object.go index 42c3f0b..c410c03 100644 --- a/object.go +++ b/object.go @@ -81,24 +81,20 @@ GoClosure* _object_closure_new(gboolean no_inst, gpointer p0) { } static inline -gulong _signal_connect(GObject* inst, guint sig, GoClosure* cl) { +gulong _signal_connect(GObject* inst, guint id, GQuark detail, GoClosure* cl) { return g_signal_connect_closure_by_id( inst, - sig, - 0, + id, + detail, (GClosure*) cl, TRUE ); } static inline -void _signal_emit(const GValue *inst_and_params, guint sig, GValue *ret) { - return g_signal_emitv( - inst_and_params, - sig, - 0, - ret - ); +void _signal_emit(const GValue *inst_and_params, guint id, GQuark detail, + GValue *ret) { + return g_signal_emitv( inst_and_params, id, detail, ret); } */ import "C" @@ -174,9 +170,9 @@ func (o *Object) GetProperty(name string) interface{} { return v.Get() } -func (o *Object) EmitById(sig SignalId, args ...interface{}) interface{} { +func (o *Object) EmitById(sid SignalId, detail Quark, args ...interface{}) interface{} { var sq C.GSignalQuery - C.g_signal_query(C.guint(sig), &sq) + C.g_signal_query(C.guint(sid), &sq) if len(args) != int(sq.n_params) { panic(fmt.Sprintf( "*Object.EmitById "+ @@ -190,12 +186,13 @@ func (o *Object) EmitById(sig SignalId, args ...interface{}) interface{} { prms[i+1] = *ValueOf(a) } ret := new(Value) - C._signal_emit(prms[0].g(), C.guint(sig), ret.g()) + C._signal_emit(prms[0].g(), C.guint(sid), C.GQuark(detail), ret.g()) return ret.Get() } func (o *Object) Emit(sig_name string, args ...interface{}) interface{} { - return o.EmitById(SignalLookup(sig_name, o.Type()), args...) + sid, detail := SignalLookup(sig_name, o.Type()) + return o.EmitById(sid, detail, args...) } type SigHandlerId C.gulong @@ -206,16 +203,18 @@ type sigHandler struct { var obj_handlers = make(map[uintptr]map[SigHandlerId]*sigHandler) -func (o *Object) connect(noi bool, sig SignalId, cb_func, param0 interface{}) { +func (o *Object) connect(noi bool, sid SignalId, detail Quark, cb_func, +param0 interface{}) { cb := reflect.ValueOf(cb_func) if cb.Kind() != reflect.Func { panic("cb_func isn't a function") } // Check that function parameters and return value match to signal var sq C.GSignalQuery - C.g_signal_query(C.guint(sig), &sq) + + C.g_signal_query(C.guint(sid), &sq) ft := cb.Type() - if ft.NumOut() > 1 || ft.NumOut() == 1 && Type(sq.return_type)== TYPE_NONE { + if ft.NumOut() > 1 || ft.NumOut() == 1 && Type(sq.return_type) == TYPE_NONE { panic("Number of function return values doesn't match signal spec.") } poffset := 2 @@ -238,12 +237,12 @@ func (o *Object) connect(noi bool, sig SignalId, cb_func, param0 interface{}) { panic("Type of function return value doesn't match signal spec.") } if n_params > 0 { - pt := (*[1<<16]Type)(unsafe.Pointer(sq.param_types))[:int(sq.n_params)] + pt := (*[1 << 16]Type)(unsafe.Pointer(sq.param_types))[:int(sq.n_params)] for i := 0; i < n_params; i++ { if !pt[i].Match(ft.In(i + poffset)) { panic(fmt.Sprintf( "Callback #%d param. type %s doesn't match signal spec %s", - i+1, ft.In(i + poffset), pt[i], + i+1, ft.In(i+poffset), pt[i], )) } } @@ -266,7 +265,7 @@ func (o *Object) connect(noi bool, sig SignalId, cb_func, param0 interface{}) { default: panic("Callback parameter #0 isn't a pointer nor nil") } - gocl.h_id = C._signal_connect(o.g(), C.guint(sig), gocl) + gocl.h_id = C._signal_connect(o.g(), C.guint(sid), C.GQuark(detail), gocl) oh := obj_handlers[uintptr(o.p)] if oh == nil { oh = make(map[SigHandlerId]*sigHandler) @@ -276,25 +275,29 @@ func (o *Object) connect(noi bool, sig SignalId, cb_func, param0 interface{}) { } // Connect callback to signal specified by id -func (o *Object) ConnectSid(sig SignalId, cb_func, param0 interface{}) { - o.connect(false, sig, cb_func, param0) +func (o *Object) ConnectSid(sid SignalId, detail Quark, +cb_func, param0 interface{}) { + o.connect(false, sid, detail, cb_func, param0) } // Connect callback to signal specified by id. // Doesn't pass o as first parameter to callback. -func (o *Object) ConnectSidNoi(sig SignalId, cb_func, param0 interface{}) { - o.connect(true, sig, cb_func, param0) +func (o *Object) ConnectSidNoi(sid SignalId, detail Quark, +cb_func, param0 interface{}) { + o.connect(true, sid, detail, cb_func, param0) } // Connect callback to signal specified by name. func (o *Object) Connect(sig_name string, cb_func, param0 interface{}) { - o.ConnectSid(SignalLookup(sig_name, o.Type()), cb_func, param0) + sid, detail := SignalLookup(sig_name, o.Type()) + o.connect(false, sid, detail, cb_func, param0) } // Connect callback to signal specified by name. // Doesn't pass o as first parameter to callback. func (o *Object) ConnectNoi(sig_name string, cb_func, param0 interface{}) { - o.ConnectSidNoi(SignalLookup(sig_name, o.Type()), cb_func, param0) + sid, detail := SignalLookup(sig_name, o.Type()) + o.connect(true, sid, detail, cb_func, param0) } type Params map[string]interface{} diff --git a/signal.go b/signal.go index 39ebd59..11cf597 100644 --- a/signal.go +++ b/signal.go @@ -8,6 +8,7 @@ import "C" import ( "unsafe" + "strings" ) type SignalFlags C.GSignalFlags @@ -49,8 +50,13 @@ func (s SignalId) String() string { return C.GoString((*C.char)(C.g_signal_name(C.guint(s)))) } -func SignalLookup(n string, t Type) SignalId { - s := C.CString(n) +func SignalLookup(name string, t Type) (sid SignalId, detail Quark) { + st := strings.SplitN(name, "::", 2) + if len(st) == 2 { + detail = QuarkFromString(st[1]) + } + s := C.CString(st[0]) + sid = SignalId(C.g_signal_lookup((*C.gchar)(s), t.g())) defer C.free(unsafe.Pointer(s)) - return SignalId(C.g_signal_lookup((*C.gchar)(s), t.g())) + return }