// IdleAdd adds an idle source to the default main event loop // context. After running once, the source func will be removed // from the main event loop, unless f returns a single bool true. // // This function will cause a panic when f eventually runs if the // types of args do not match those of f. func IdleAdd(f interface{}, args ...interface{}) (SourceHandle, error) { // f must be a func with no parameters. rf := reflect.ValueOf(f) if rf.Type().Kind() != reflect.Func { return 0, errors.New("f is not a function") } // Create an idle source func for a main loop context. idleSrc := C.g_idle_source_new() if idleSrc == nil { return 0, nilPtrErr } // Create a new GClosure from f that invalidates itself when // f returns false. The error is ignored here, as this will // always be a function. var closure *C.GClosure closure, _ = ClosureNew(func() { // Create a slice of reflect.Values arguments to call the func. rargs := make([]reflect.Value, len(args)) for i := range args { rargs[i] = reflect.ValueOf(args[i]) } // Call func with args. The callback will be removed, unless // it returns exactly one return value of true. rv := rf.Call(rargs) if len(rv) == 1 { if rv[0].Kind() == reflect.Bool { if rv[0].Bool() { return } } } C.g_closure_invalidate(closure) C.g_source_destroy(idleSrc) }) // Remove closure context when closure is finalized. C._g_closure_add_finalize_notifier(closure) // Set closure to run as a callback when the idle source runs. C.g_source_set_closure(idleSrc, closure) // Attach the idle source func to the default main event loop // context. cid := C.g_source_attach(idleSrc, nil) return SourceHandle(cid), nil }
// Connect is a wrapper around g_signal_connect_closure(). f must be // a function with a signaure matching the callback signature for // detailedSignal. userData must either 0 or 1 elements which can // be optionally passed to f. If f takes less arguments than it is // passed from the GLib runtime, the extra arguments are ignored. // // Arguments for f must be a matching Go equivalent type for the // C callback, or an interface type which the value may be packed in. // If the type is not suitable, a runtime panic will occur when the // signal is emitted. func (v *Object) Connect(detailedSignal string, f interface{}, userData ...interface{}) (SignalHandle, error) { if len(userData) > 1 { return 0, errors.New("userData len must be 0 or 1") } cstr := C.CString(detailedSignal) defer C.free(unsafe.Pointer(cstr)) closure, err := ClosureNew(f, userData...) if err != nil { return 0, err } C._g_closure_add_finalize_notifier(closure) c := C.g_signal_connect_closure(C.gpointer(v.native()), (*C.gchar)(cstr), closure, gbool(false)) handle := SignalHandle(c) // Map the signal handle to the closure. signals[handle] = closure return handle, nil }