Example #1
0
File: glib.go Project: vvanpo/gotk3
// 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()
}
Example #2
0
File: gobj.go Project: hwch/go-gtk
//--------------------------------------------------------------
// 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))
}
Example #3
0
File: gobj.go Project: hwch/go-gtk
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)
}
Example #4
0
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()
}
Example #5
0
func (q Quark) GQuark() C.GQuark {
	return C.GQuark(q)
}
Example #6
0
// 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)))
}
Example #7
0
File: gobj.go Project: hwch/go-gtk
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))
}
Example #8
0
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
}