// Emit is a wrapper around g_signal_emitv() and emits the signal // specified by the string s to an Object. Arguments to callback // functions connected to this signal must be specified in args. Emit() // returns an interface{} which must be type asserted as the Go // equivalent type to the return value for native C callback. // // Note that this code is unsafe in that the types of values in args are // not checked against whether they are suitable for the callback. func (v *Object) Emit(s string, args ...interface{}) (interface{}, error) { cstr := C.CString(s) defer C.free(unsafe.Pointer(cstr)) // Create array of this instance and arguments valv := C.alloc_gvalue_list(C.int(len(args)) + 1) defer C.free(unsafe.Pointer(valv)) // Add args and valv val, err := GValue(v) if err != nil { return nil, errors.New("Error converting Object to GValue: " + err.Error()) } C.val_list_insert(valv, C.int(0), val.native()) for i := range args { val, err := GValue(args[i]) if err != nil { return nil, fmt.Errorf("Error converting arg %d to GValue: %s", i, err.Error()) } C.val_list_insert(valv, C.int(i+1), val.native()) } t := v.TypeFromInstance() // TODO: use just the signal name id := C.g_signal_lookup((*C.gchar)(cstr), C.GType(t)) ret, err := ValueAlloc() if err != nil { return nil, errors.New("Error creating Value for return value") } C.g_signal_emitv(valv, id, C.GQuark(0), ret.native()) return ret.GoValue() }
//-------------------------------------------------------------- // Object //-------------------------------------------------------------- func objectFinalizer(obj *Object) { if FQueue.Push(unsafe.Pointer(obj), objectFinalizer2) { return } C.g_object_set_qdata((*C.GObject)(obj.C), C.GQuark(go_repr), nil) C.g_object_unref(C.gpointer(obj.C)) }
func ObjectWrap(c unsafe.Pointer, grab bool) unsafe.Pointer { if c == nil { return nil } obj := (*Object)(C.g_object_get_qdata((*C.GObject)(c), C.GQuark(go_repr))) if obj != nil { return unsafe.Pointer(obj) } obj = &Object{c} if grab { C.g_object_ref_sink(C.gpointer(obj.C)) } setObjectFinalizer(obj) C.g_object_set_qdata((*C.GObject)(obj.C), C.GQuark(go_repr), unsafe.Pointer(obj)) return unsafe.Pointer(obj) }
func (o *Object) EmitById(sid SignalId, detail Quark, args ...interface{}) interface{} { var sq C.GSignalQuery C.g_signal_query(C.guint(sid), &sq) if len(args) != int(sq.n_params) { panic(fmt.Sprintf( "*Object.EmitById "+ "Number of input parameters #%d doesn't match signal spec #%d", len(args), int(sq.n_params), )) } prms := make([]Value, len(args)+1) prms[0] = *ValueOf(o) for i, a := range args { prms[i+1] = *ValueOf(a) } ret := new(Value) C._signal_emit(prms[0].g(), C.guint(sid), C.GQuark(detail), ret.g()) return ret.Get() }
func (q Quark) GQuark() C.GQuark { return C.GQuark(q) }
// Activate is a wrapper around gtk_accel_group_activate(). func (v *AccelGroup) Activate(quark glib.Quark, acceleratable *glib.Object, key uint, mods gdk.ModifierType) bool { return gobool(C.gtk_accel_group_activate(v.native(), C.GQuark(quark), (*C.GObject)(unsafe.Pointer(acceleratable.Native())), C.guint(key), C.GdkModifierType(mods))) }
func objectFinalizer2(objc unsafe.Pointer) { obj := (*Object)(objc) C.g_object_set_qdata((*C.GObject)(obj.C), C.GQuark(go_repr), nil) C.g_object_unref(C.gpointer(obj.C)) }
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(sid), &sq) ft := cb.Type() 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 if param0 == nil { // There is no param0 poffset-- } if noi { // There is no instance on which signal was emited as first parameter poffset-- } else if !o.Type().Match(ft.In(poffset - 1)) { panic(fmt.Sprintf( "Callback #%d param. type %s doesn't match signal source: %s", poffset-1, ft.In(poffset-1), o.Type(), )) } n_params := int(sq.n_params) if ft.NumIn() != n_params+poffset { panic(fmt.Sprintf( "Number of function parameters #%d isn't equal to signal spec: #%d", ft.NumIn(), n_params+poffset, )) } if ft.NumOut() != 0 && !Type(sq.return_type).Match(ft.Out(0)) { 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)] 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+poffset, ft.In(i+poffset), pt[i], )) } } } // Setup closure and connect it to signal var gocl *C.GoClosure p0 := reflect.ValueOf(param0) // Check type of #0 parameter which is set by Connect method switch p0.Kind() { case reflect.Invalid: gocl = C._object_closure_new(gBoolean(noi), nil) case reflect.Ptr: if !p0.Type().AssignableTo(ft.In(0)) { panic(fmt.Sprintf( "Callback #0 parameter type: %s doesn't match signal spec: %s", ft.In(0), p0.Type(), )) } gocl = C._object_closure_new(gBoolean(noi), C.gpointer(p0.Pointer())) default: panic("Callback parameter #0 isn't a pointer nor nil") } 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) obj_handlers[uintptr(o.p)] = oh } oh[SigHandlerId(gocl.h_id)] = &sigHandler{cb, p0} // p0 for prevent GC }