1// Copyright (c) 2013-2014 Conformal Systems <info@conformal.com>
2//
3// This file originated from: http://opensource.conformal.com/
4//
5// Permission to use, copy, modify, and distribute this software for any
6// purpose with or without fee is hereby granted, provided that the above
7// copyright notice and this permission notice appear in all copies.
8//
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17// Package glib provides Go bindings for GLib 2. It supports version 2.36 and
18// later.
19package glib
20
21// #cgo pkg-config: gio-2.0 glib-2.0 gobject-2.0
22// #include <gio/gio.h>
23// #include <stdlib.h>
24// #include <glib.h>
25// #include <glib-object.h>
26// #include "glib.go.h"
27import "C"
28
29import (
30	"errors"
31	"fmt"
32	"reflect"
33	"runtime"
34	"unsafe"
35
36	"github.com/gotk3/gotk3/internal/callback"
37	"github.com/gotk3/gotk3/internal/closure"
38)
39
40/*
41 * Type conversions
42 */
43
44func gbool(b bool) C.gboolean {
45	if b {
46		return C.gboolean(1)
47	}
48	return C.gboolean(0)
49}
50
51func gobool(b C.gboolean) bool {
52	if b != 0 {
53		return true
54	}
55	return false
56}
57
58/*
59 * Unexported vars
60 */
61
62var nilPtrErr = errors.New("cgo returned unexpected nil pointer")
63
64/*
65 * Constants
66 */
67
68// Type is a representation of GLib's GType.
69type Type uint
70
71const (
72	TYPE_INVALID   Type = C.G_TYPE_INVALID
73	TYPE_NONE      Type = C.G_TYPE_NONE
74	TYPE_INTERFACE Type = C.G_TYPE_INTERFACE
75	TYPE_CHAR      Type = C.G_TYPE_CHAR
76	TYPE_UCHAR     Type = C.G_TYPE_UCHAR
77	TYPE_BOOLEAN   Type = C.G_TYPE_BOOLEAN
78	TYPE_INT       Type = C.G_TYPE_INT
79	TYPE_UINT      Type = C.G_TYPE_UINT
80	TYPE_LONG      Type = C.G_TYPE_LONG
81	TYPE_ULONG     Type = C.G_TYPE_ULONG
82	TYPE_INT64     Type = C.G_TYPE_INT64
83	TYPE_UINT64    Type = C.G_TYPE_UINT64
84	TYPE_ENUM      Type = C.G_TYPE_ENUM
85	TYPE_FLAGS     Type = C.G_TYPE_FLAGS
86	TYPE_FLOAT     Type = C.G_TYPE_FLOAT
87	TYPE_DOUBLE    Type = C.G_TYPE_DOUBLE
88	TYPE_STRING    Type = C.G_TYPE_STRING
89	TYPE_POINTER   Type = C.G_TYPE_POINTER
90	TYPE_BOXED     Type = C.G_TYPE_BOXED
91	TYPE_PARAM     Type = C.G_TYPE_PARAM
92	TYPE_OBJECT    Type = C.G_TYPE_OBJECT
93	TYPE_VARIANT   Type = C.G_TYPE_VARIANT
94)
95
96// IsValue checks whether the passed in type can be used for g_value_init().
97func (t Type) IsValue() bool {
98	return gobool(C._g_type_is_value(C.GType(t)))
99}
100
101// Name is a wrapper around g_type_name().
102func (t Type) Name() string {
103	return C.GoString((*C.char)(C.g_type_name(C.GType(t))))
104}
105
106// Depth is a wrapper around g_type_depth().
107func (t Type) Depth() uint {
108	return uint(C.g_type_depth(C.GType(t)))
109}
110
111// Parent is a wrapper around g_type_parent().
112func (t Type) Parent() Type {
113	return Type(C.g_type_parent(C.GType(t)))
114}
115
116// IsA is a wrapper around g_type_is_a().
117func (t Type) IsA(isAType Type) bool {
118	return gobool(C.g_type_is_a(C.GType(t), C.GType(isAType)))
119}
120
121// TypeFromName is a wrapper around g_type_from_name
122func TypeFromName(typeName string) Type {
123	cstr := (*C.gchar)(C.CString(typeName))
124	defer C.free(unsafe.Pointer(cstr))
125	return Type(C.g_type_from_name(cstr))
126}
127
128//TypeNextBase is a wrapper around g_type_next_base
129func TypeNextBase(leafType, rootType Type) Type {
130	return Type(C.g_type_next_base(C.GType(leafType), C.GType(rootType)))
131}
132
133// SettingsBindFlags is a representation of GLib's GSettingsBindFlags.
134type SettingsBindFlags int
135
136const (
137	SETTINGS_BIND_DEFAULT        SettingsBindFlags = C.G_SETTINGS_BIND_DEFAULT
138	SETTINGS_BIND_GET            SettingsBindFlags = C.G_SETTINGS_BIND_GET
139	SETTINGS_BIND_SET            SettingsBindFlags = C.G_SETTINGS_BIND_SET
140	SETTINGS_BIND_NO_SENSITIVITY SettingsBindFlags = C.G_SETTINGS_BIND_NO_SENSITIVITY
141	SETTINGS_BIND_GET_NO_CHANGES SettingsBindFlags = C.G_SETTINGS_BIND_GET_NO_CHANGES
142	SETTINGS_BIND_INVERT_BOOLEAN SettingsBindFlags = C.G_SETTINGS_BIND_INVERT_BOOLEAN
143)
144
145// UserDirectory is a representation of GLib's GUserDirectory.
146type UserDirectory int
147
148const (
149	USER_DIRECTORY_DESKTOP      UserDirectory = C.G_USER_DIRECTORY_DESKTOP
150	USER_DIRECTORY_DOCUMENTS    UserDirectory = C.G_USER_DIRECTORY_DOCUMENTS
151	USER_DIRECTORY_DOWNLOAD     UserDirectory = C.G_USER_DIRECTORY_DOWNLOAD
152	USER_DIRECTORY_MUSIC        UserDirectory = C.G_USER_DIRECTORY_MUSIC
153	USER_DIRECTORY_PICTURES     UserDirectory = C.G_USER_DIRECTORY_PICTURES
154	USER_DIRECTORY_PUBLIC_SHARE UserDirectory = C.G_USER_DIRECTORY_PUBLIC_SHARE
155	USER_DIRECTORY_TEMPLATES    UserDirectory = C.G_USER_DIRECTORY_TEMPLATES
156	USER_DIRECTORY_VIDEOS       UserDirectory = C.G_USER_DIRECTORY_VIDEOS
157)
158
159const USER_N_DIRECTORIES int = C.G_USER_N_DIRECTORIES
160
161/*
162 * GApplicationFlags
163 */
164
165type ApplicationFlags int
166
167const (
168	APPLICATION_FLAGS_NONE           ApplicationFlags = C.G_APPLICATION_FLAGS_NONE
169	APPLICATION_IS_SERVICE           ApplicationFlags = C.G_APPLICATION_IS_SERVICE
170	APPLICATION_HANDLES_OPEN         ApplicationFlags = C.G_APPLICATION_HANDLES_OPEN
171	APPLICATION_HANDLES_COMMAND_LINE ApplicationFlags = C.G_APPLICATION_HANDLES_COMMAND_LINE
172	APPLICATION_SEND_ENVIRONMENT     ApplicationFlags = C.G_APPLICATION_SEND_ENVIRONMENT
173	APPLICATION_NON_UNIQUE           ApplicationFlags = C.G_APPLICATION_NON_UNIQUE
174)
175
176// goMarshal is called by the GLib runtime when a closure needs to be invoked.
177// The closure will be invoked with as many arguments as it can take, from 0 to
178// the full amount provided by the call. If the closure asks for more parameters
179// than there are to give, then a runtime panic will occur.
180//
181//export goMarshal
182func goMarshal(
183	gclosure *C.GClosure,
184	retValue *C.GValue,
185	nParams C.guint,
186	params *C.GValue,
187	invocationHint C.gpointer,
188	marshalData *C.GValue) {
189
190	// Get the function value associated with this callback closure.
191	fs := closure.Get(unsafe.Pointer(gclosure))
192	if !fs.IsValid() {
193		// Possible data race, bail.
194		return
195	}
196
197	fsType := fs.Func.Type()
198
199	// Get number of parameters passed in.
200	nGLibParams := int(nParams)
201	nTotalParams := nGLibParams
202
203	// Reflect may panic, so we defer recover here to re-panic with our trace.
204	defer fs.TryRepanic()
205
206	// Get number of parameters from the callback closure. If this exceeds
207	// the total number of marshaled parameters, trigger a runtime panic.
208	nCbParams := fsType.NumIn()
209	if nCbParams > nTotalParams {
210		fs.Panicf("too many closure args: have %d, max %d", nCbParams, nTotalParams)
211	}
212
213	// Create a slice of reflect.Values as arguments to call the function.
214	gValues := gValueSlice(params, nCbParams)
215	args := make([]reflect.Value, 0, nCbParams)
216
217	// Fill beginning of args, up to the minimum of the total number of callback
218	// parameters and parameters from the glib runtime.
219	for i := 0; i < nCbParams && i < nGLibParams; i++ {
220		v := Value{&gValues[i]}
221
222		val, err := v.GoValue()
223		if err != nil {
224			fs.Panicf("no suitable Go value for arg %d: %v", i, err)
225		}
226
227		// Parameters that are descendants of GObject come wrapped in another
228		// GObject. For C applications, the default marshaller
229		// (g_cclosure_marshal_VOID__VOID in gmarshal.c in the GTK glib library)
230		// 'peeks' into the enclosing object and passes the wrapped object to
231		// the handler. Use the *Object.goValue function to emulate that for Go
232		// signal handlers.
233		switch objVal := val.(type) {
234		case *Object:
235			if innerVal, err := objVal.goValue(); err == nil {
236				val = innerVal
237			}
238
239		case *Variant:
240			switch ts := objVal.TypeString(); ts {
241			case "s":
242				val = objVal.GetString()
243			case "b":
244				val = gobool(C.g_variant_get_boolean(objVal.native()))
245			case "d":
246				val = float64(C.g_variant_get_double(objVal.native()))
247			case "n":
248				val = int16(C.g_variant_get_int16(objVal.native()))
249			case "i":
250				val = int32(C.g_variant_get_int32(objVal.native()))
251			case "x":
252				val = int64(C.g_variant_get_int64(objVal.native()))
253			case "y":
254				val = uint8(C.g_variant_get_byte(objVal.native()))
255			case "q":
256				val = uint16(C.g_variant_get_uint16(objVal.native()))
257			case "u":
258				val = uint32(C.g_variant_get_uint32(objVal.native()))
259			case "t":
260				val = uint64(C.g_variant_get_uint64(objVal.native()))
261			default:
262				fs.Panicf("variant conversion not yet implemented for type %s", ts)
263			}
264		}
265
266		args = append(args, reflect.ValueOf(val).Convert(fsType.In(i)))
267	}
268
269	// Call closure with args. If the callback returns one or more values, save
270	// the GValue equivalent of the first.
271	rv := fs.Func.Call(args)
272	if retValue != nil && len(rv) > 0 {
273		g, err := GValue(rv[0].Interface())
274		if err != nil {
275			fs.Panicf("cannot save callback return value: %v", err)
276		}
277
278		t, _, err := g.Type()
279		if err != nil {
280			fs.Panicf("cannot determine callback return value: %v", err)
281		}
282
283		// Explicitly copy the return value as it may point to go-owned memory.
284		C.g_value_unset(retValue)
285		C.g_value_init(retValue, C.GType(t))
286		C.g_value_copy(g.native(), retValue)
287	}
288}
289
290// gValueSlice converts a C array of GValues to a Go slice.
291func gValueSlice(values *C.GValue, nValues int) (slice []C.GValue) {
292	header := (*reflect.SliceHeader)((unsafe.Pointer(&slice)))
293	header.Cap = nValues
294	header.Len = nValues
295	header.Data = uintptr(unsafe.Pointer(values))
296	return
297}
298
299/*
300 * Main event loop
301 */
302
303// Priority is the enumerated type for GLib priority event sources.
304type Priority int
305
306const (
307	PRIORITY_HIGH         Priority = C.G_PRIORITY_HIGH
308	PRIORITY_DEFAULT      Priority = C.G_PRIORITY_DEFAULT // TimeoutAdd
309	PRIORITY_HIGH_IDLE    Priority = C.G_PRIORITY_HIGH_IDLE
310	PRIORITY_DEFAULT_IDLE Priority = C.G_PRIORITY_DEFAULT_IDLE // IdleAdd
311	PRIORITY_LOW          Priority = C.G_PRIORITY_LOW
312)
313
314type SourceHandle uint
315
316// sourceFunc is the callback for g_idle_add_full and g_timeout_add_full that
317// replaces the GClosure API.
318//
319//export sourceFunc
320func sourceFunc(data C.gpointer) C.gboolean {
321	v := callback.Get(uintptr(data))
322	fs := v.(closure.FuncStack)
323
324	rv := fs.Func.Call(nil)
325	if len(rv) == 1 && rv[0].Bool() {
326		return C.TRUE
327	}
328
329	return C.FALSE
330}
331
332//export removeSourceFunc
333func removeSourceFunc(data C.gpointer) {
334	callback.Delete(uintptr(data))
335}
336
337var (
338	_sourceFunc       = (*[0]byte)(C.sourceFunc)
339	_removeSourceFunc = (*[0]byte)(C.removeSourceFunc)
340)
341
342// IdleAdd adds an idle source to the default main event loop context with the
343// DefaultIdle priority. If f is not a function with no parameter, then IdleAdd
344// will panic.
345//
346// After running once, the source func will be removed from the main event loop,
347// unless f returns a single bool true.
348func IdleAdd(f interface{}) SourceHandle {
349	return idleAdd(PRIORITY_DEFAULT_IDLE, f)
350}
351
352// IdleAddPriority adds an idle source to the default main event loop context
353// with the given priority. Its behavior is the same as IdleAdd.
354func IdleAddPriority(priority Priority, f interface{}) SourceHandle {
355	return idleAdd(priority, f)
356}
357
358func idleAdd(priority Priority, f interface{}) SourceHandle {
359	fs := closure.NewIdleFuncStack(f, 2)
360	id := C.gpointer(callback.Assign(fs))
361	h := C.g_idle_add_full(C.gint(priority), _sourceFunc, id, _removeSourceFunc)
362
363	return SourceHandle(h)
364}
365
366// TimeoutAdd adds an timeout source to the default main event loop context.
367// Timeout is in milliseconds. If f is not a function with no parameter, then it
368// will panic.
369//
370// After running once, the source func will be removed from the main event loop,
371// unless f returns a single bool true.
372func TimeoutAdd(milliseconds uint, f interface{}) SourceHandle {
373	return timeoutAdd(milliseconds, false, PRIORITY_DEFAULT, f)
374}
375
376// TimeoutAddPriority is similar to TimeoutAdd with the given priority. Refer to
377// TimeoutAdd for more information.
378func TimeoutAddPriority(milliseconds uint, priority Priority, f interface{}) SourceHandle {
379	return timeoutAdd(milliseconds, false, priority, f)
380}
381
382// TimeoutSecondsAdd is similar to TimeoutAdd, except with seconds granularity.
383func TimeoutSecondsAdd(seconds uint, f interface{}) SourceHandle {
384	return timeoutAdd(seconds, true, PRIORITY_DEFAULT, f)
385}
386
387// TimeoutSecondsAddPriority adds a timeout source with the given priority.
388// Refer to TimeoutSecondsAdd for more information.
389func TimeoutSecondsAddPriority(seconds uint, priority Priority, f interface{}) SourceHandle {
390	return timeoutAdd(seconds, true, priority, f)
391}
392
393func timeoutAdd(time uint, sec bool, priority Priority, f interface{}) SourceHandle {
394	fs := closure.NewIdleFuncStack(f, 2)
395	id := C.gpointer(callback.Assign(fs))
396
397	var h C.guint
398	if sec {
399		h = C.g_timeout_add_seconds_full(C.gint(priority), C.guint(time), _sourceFunc, id, _removeSourceFunc)
400	} else {
401		h = C.g_timeout_add_full(C.gint(priority), C.guint(time), _sourceFunc, id, _removeSourceFunc)
402	}
403
404	return SourceHandle(h)
405}
406
407// Destroy is a wrapper around g_source_destroy()
408func (v *Source) Destroy() {
409	C.g_source_destroy(v.native())
410}
411
412// IsDestroyed is a wrapper around g_source_is_destroyed()
413func (v *Source) IsDestroyed() bool {
414	return gobool(C.g_source_is_destroyed(v.native()))
415}
416
417// Unref is a wrapper around g_source_unref()
418func (v *Source) Unref() {
419	C.g_source_unref(v.native())
420}
421
422// Ref is a wrapper around g_source_ref()
423func (v *Source) Ref() *Source {
424	c := C.g_source_ref(v.native())
425	if c == nil {
426		return nil
427	}
428	return (*Source)(c)
429}
430
431// SourceRemove is a wrapper around g_source_remove()
432func SourceRemove(src SourceHandle) bool {
433	return gobool(C.g_source_remove(C.guint(src)))
434}
435
436/*
437 * Miscellaneous Utility Functions
438 */
439
440// GetHomeDir is a wrapper around g_get_home_dir().
441func GetHomeDir() string {
442	c := C.g_get_home_dir()
443	return C.GoString((*C.char)(c))
444}
445
446// GetUserCacheDir is a wrapper around g_get_user_cache_dir().
447func GetUserCacheDir() string {
448	c := C.g_get_user_cache_dir()
449	return C.GoString((*C.char)(c))
450}
451
452// GetUserDataDir is a wrapper around g_get_user_data_dir().
453func GetUserDataDir() string {
454	c := C.g_get_user_data_dir()
455	return C.GoString((*C.char)(c))
456}
457
458// GetUserConfigDir is a wrapper around g_get_user_config_dir().
459func GetUserConfigDir() string {
460	c := C.g_get_user_config_dir()
461	return C.GoString((*C.char)(c))
462}
463
464// GetUserRuntimeDir is a wrapper around g_get_user_runtime_dir().
465func GetUserRuntimeDir() string {
466	c := C.g_get_user_runtime_dir()
467	return C.GoString((*C.char)(c))
468}
469
470// GetUserSpecialDir is a wrapper around g_get_user_special_dir().  A
471// non-nil error is returned in the case that g_get_user_special_dir()
472// returns NULL to differentiate between NULL and an empty string.
473func GetUserSpecialDir(directory UserDirectory) (string, error) {
474	c := C.g_get_user_special_dir(C.GUserDirectory(directory))
475	if c == nil {
476		return "", nilPtrErr
477	}
478	return C.GoString((*C.char)(c)), nil
479}
480
481// FormatSize is a wrapper around g_format_size().
482func FormatSize(size uint64) string {
483	char := C.g_format_size(C.guint64(size))
484	defer C.free(unsafe.Pointer(char))
485
486	return C.GoString(char)
487}
488
489// FormatSizeFlags are flags to modify the format of the string returned by
490// FormatSizeFull.
491type FormatSizeFlags int
492
493const (
494	FORMAT_SIZE_DEFAULT     FormatSizeFlags = C.G_FORMAT_SIZE_DEFAULT
495	FORMAT_SIZE_LONG_FORMAT FormatSizeFlags = C.G_FORMAT_SIZE_LONG_FORMAT
496	FORMAT_SIZE_IEC_UNITS   FormatSizeFlags = C.G_FORMAT_SIZE_IEC_UNITS
497	FORMAT_SIZE_BITS        FormatSizeFlags = C.G_FORMAT_SIZE_BITS
498)
499
500// FormatSizeFull is a wrapper around g_format_size_full().
501func FormatSizeFull(size uint64, flags FormatSizeFlags) string {
502	char := C.g_format_size_full(C.guint64(size), C.GFormatSizeFlags(flags))
503	defer C.free(unsafe.Pointer(char))
504
505	return C.GoString(char)
506}
507
508// SpacedPrimesClosest is a wrapper around g_spaced_primes_closest().
509func SpacedPrimesClosest(num uint) uint {
510	return uint(C.g_spaced_primes_closest(C.guint(num)))
511}
512
513/*
514 * GObject
515 */
516
517// IObject is an interface type implemented by Object and all types which embed
518// an Object. It is meant to be used as a type for function arguments which
519// require GObjects or any subclasses thereof.
520type IObject interface {
521	toGObject() *C.GObject
522	toObject() *Object
523}
524
525// Object is a representation of GLib's GObject.
526type Object struct {
527	GObject *C.GObject
528}
529
530func (v *Object) toGObject() *C.GObject {
531	if v == nil {
532		return nil
533	}
534	return v.native()
535}
536
537func (v *Object) toObject() *Object {
538	return v
539}
540
541// newObject creates a new Object from a GObject pointer.
542func newObject(p *C.GObject) *Object {
543	if p == nil {
544		return nil
545	}
546	return &Object{GObject: p}
547}
548
549// native returns a pointer to the underlying GObject.
550func (v *Object) native() *C.GObject {
551	if v == nil || v.GObject == nil {
552		return nil
553	}
554	p := unsafe.Pointer(v.GObject)
555	return C.toGObject(p)
556}
557
558// goValue converts a *Object to a Go type (e.g. *Object => *gtk.Entry).
559// It is used in goMarshal to convert generic GObject parameters to
560// signal handlers to the actual types expected by the signal handler.
561func (v *Object) goValue() (interface{}, error) {
562	objType := Type(C._g_type_from_instance(C.gpointer(v.native())))
563	f, err := gValueMarshalers.lookupType(objType)
564	if err != nil {
565		return nil, err
566	}
567
568	// The marshalers expect Values, not Objects
569	val, err := ValueInit(objType)
570	if err != nil {
571		return nil, err
572	}
573	val.SetInstance(uintptr(unsafe.Pointer(v.GObject)))
574	rv, err := f(uintptr(unsafe.Pointer(val.native())))
575	return rv, err
576}
577
578// Take wraps a unsafe.Pointer as a glib.Object, taking ownership of it.
579// This function is exported for visibility in other gotk3 packages and
580// is not meant to be used by applications.
581//
582// To be clear, this should mostly be used when Gtk says "transfer none". Refer
583// to AssumeOwnership for more details.
584func Take(ptr unsafe.Pointer) *Object {
585	obj := newObject(ToGObject(ptr))
586	if obj == nil {
587		return nil
588	}
589
590	obj.RefSink()
591	runtime.SetFinalizer(obj, (*Object).Unref)
592	return obj
593}
594
595// AssumeOwnership is similar to Take, except the function does not take a
596// reference. This is usually used for newly constructed objects that for some
597// reason does not have an initial floating reference.
598//
599// To be clear, this should often be used when Gtk says "transfer full", as it
600// means the ownership is transferred to the caller, so we can assume that much.
601// This is in contrary to Take, which is used when Gtk says "transfer none", as
602// we're now referencing an object that might possibly be kept, so we should
603// mark as such.
604func AssumeOwnership(ptr unsafe.Pointer) *Object {
605	obj := newObject(ToGObject(ptr))
606	runtime.SetFinalizer(obj, (*Object).Unref)
607	return obj
608}
609
610// Native returns a pointer to the underlying GObject.
611func (v *Object) Native() uintptr {
612	return uintptr(unsafe.Pointer(v.native()))
613}
614
615// IsA is a wrapper around g_type_is_a().
616func (v *Object) IsA(typ Type) bool {
617	return gobool(C.g_type_is_a(C.GType(v.TypeFromInstance()), C.GType(typ)))
618}
619
620// TypeFromInstance is a wrapper around g_type_from_instance().
621func (v *Object) TypeFromInstance() Type {
622	c := C._g_type_from_instance(C.gpointer(unsafe.Pointer(v.native())))
623	return Type(c)
624}
625
626// ToGObject type converts an unsafe.Pointer as a native C GObject.
627// This function is exported for visibility in other gotk3 packages and
628// is not meant to be used by applications.
629func ToGObject(p unsafe.Pointer) *C.GObject {
630	return (*C.GObject)(p)
631	// return C.toGObject(p)
632}
633
634// Ref is a wrapper around g_object_ref().
635func (v *Object) Ref() {
636	C.g_object_ref(C.gpointer(v.GObject))
637}
638
639// Unref is a wrapper around g_object_unref().
640func (v *Object) Unref() {
641	C.g_object_unref(C.gpointer(v.GObject))
642}
643
644// RefSink is a wrapper around g_object_ref_sink().
645func (v *Object) RefSink() {
646	C.g_object_ref_sink(C.gpointer(v.GObject))
647}
648
649// IsFloating is a wrapper around g_object_is_floating().
650func (v *Object) IsFloating() bool {
651	c := C.g_object_is_floating(C.gpointer(v.GObject))
652	return gobool(c)
653}
654
655// ForceFloating is a wrapper around g_object_force_floating().
656func (v *Object) ForceFloating() {
657	C.g_object_force_floating(v.GObject)
658}
659
660// StopEmission is a wrapper around g_signal_stop_emission_by_name().
661func (v *Object) StopEmission(s string) {
662	cstr := C.CString(s)
663	defer C.free(unsafe.Pointer(cstr))
664	C.g_signal_stop_emission_by_name((C.gpointer)(v.GObject),
665		(*C.gchar)(cstr))
666}
667
668// Set calls SetProperty.
669func (v *Object) Set(name string, value interface{}) error {
670	return v.SetProperty(name, value)
671}
672
673// GetPropertyType returns the Type of a property of the underlying GObject.
674// If the property is missing it will return TYPE_INVALID and an error.
675func (v *Object) GetPropertyType(name string) (Type, error) {
676	cstr := C.CString(name)
677	defer C.free(unsafe.Pointer(cstr))
678
679	paramSpec := C.g_object_class_find_property(C._g_object_get_class(v.native()), (*C.gchar)(cstr))
680	if paramSpec == nil {
681		return TYPE_INVALID, errors.New("couldn't find Property")
682	}
683	return Type(paramSpec.value_type), nil
684}
685
686// GetProperty is a wrapper around g_object_get_property().
687func (v *Object) GetProperty(name string) (interface{}, error) {
688	cstr := C.CString(name)
689	defer C.free(unsafe.Pointer(cstr))
690
691	t, err := v.GetPropertyType(name)
692	if err != nil {
693		return nil, err
694	}
695
696	p, err := ValueInit(t)
697	if err != nil {
698		return nil, errors.New("unable to allocate value")
699	}
700	C.g_object_get_property(v.GObject, (*C.gchar)(cstr), p.native())
701	return p.GoValue()
702}
703
704// SetProperty is a wrapper around g_object_set_property().
705func (v *Object) SetProperty(name string, value interface{}) error {
706	cstr := C.CString(name)
707	defer C.free(unsafe.Pointer(cstr))
708
709	if _, ok := value.(Object); ok {
710		value = value.(Object).GObject
711	}
712
713	p, err := GValue(value)
714	if err != nil {
715		return errors.New("Unable to perform type conversion")
716	}
717	C.g_object_set_property(v.GObject, (*C.gchar)(cstr), p.native())
718	return nil
719}
720
721/*
722 * GObject Signals
723 */
724
725// Emit is a wrapper around g_signal_emitv() and emits the signal
726// specified by the string s to an Object.  Arguments to callback
727// functions connected to this signal must be specified in args.  Emit()
728// returns an interface{} which must be type asserted as the Go
729// equivalent type to the return value for native C callback.
730//
731// Note that this code is unsafe in that the types of values in args are
732// not checked against whether they are suitable for the callback.
733func (v *Object) Emit(s string, args ...interface{}) (interface{}, error) {
734	cstr := C.CString(s)
735	defer C.free(unsafe.Pointer(cstr))
736
737	// Create array of this instance and arguments
738	valv := C.alloc_gvalue_list(C.int(len(args)) + 1)
739	defer C.free(unsafe.Pointer(valv))
740
741	// Add args and valv
742	val, err := GValue(v)
743	if err != nil {
744		return nil, errors.New("Error converting Object to GValue: " + err.Error())
745	}
746	C.val_list_insert(valv, C.int(0), val.native())
747	for i := range args {
748		val, err := GValue(args[i])
749		if err != nil {
750			return nil, fmt.Errorf("Error converting arg %d to GValue: %s", i, err.Error())
751		}
752		C.val_list_insert(valv, C.int(i+1), val.native())
753	}
754
755	t := v.TypeFromInstance()
756	// TODO: use just the signal name
757	id := C.g_signal_lookup((*C.gchar)(cstr), C.GType(t))
758
759	ret, err := ValueAlloc()
760	if err != nil {
761		return nil, errors.New("Error creating Value for return value")
762	}
763	C.g_signal_emitv(valv, id, C.GQuark(0), ret.native())
764
765	return ret.GoValue()
766}
767
768// HandlerBlock is a wrapper around g_signal_handler_block().
769func (v *Object) HandlerBlock(handle SignalHandle) {
770	C.g_signal_handler_block(C.gpointer(v.GObject), C.gulong(handle))
771}
772
773// HandlerUnblock is a wrapper around g_signal_handler_unblock().
774func (v *Object) HandlerUnblock(handle SignalHandle) {
775	C.g_signal_handler_unblock(C.gpointer(v.GObject), C.gulong(handle))
776}
777
778// HandlerDisconnect is a wrapper around g_signal_handler_disconnect().
779func (v *Object) HandlerDisconnect(handle SignalHandle) {
780	// Ensure that Gtk will not use the closure beforehand.
781	C.g_signal_handler_disconnect(C.gpointer(v.GObject), C.gulong(handle))
782	closure.DisconnectSignal(uint(handle))
783}
784
785// Wrapper function for new objects with reference management.
786func wrapObject(ptr unsafe.Pointer) *Object {
787	return Take(ptr)
788}
789
790/*
791 * GInitiallyUnowned
792 */
793
794// InitiallyUnowned is a representation of GLib's GInitiallyUnowned.
795type InitiallyUnowned struct {
796	// This must be a pointer so copies of the ref-sinked object
797	// do not outlive the original object, causing an unref
798	// finalizer to prematurely run.
799	*Object
800}
801
802// Native returns a pointer to the underlying GObject.  This is implemented
803// here rather than calling Native on the embedded Object to prevent a nil
804// pointer dereference.
805func (v *InitiallyUnowned) Native() uintptr {
806	if v == nil || v.Object == nil {
807		return uintptr(unsafe.Pointer(nil))
808	}
809	return v.Object.Native()
810}
811
812/*
813 * GValue
814 */
815
816// Value is a representation of GLib's GValue.
817//
818// Don't allocate Values on the stack or heap manually as they may not
819// be properly unset when going out of scope. Instead, use ValueAlloc(),
820// which will set the runtime finalizer to unset the Value after it has
821// left scope.
822type Value struct {
823	GValue *C.GValue
824}
825
826// native returns a pointer to the underlying GValue.
827func (v *Value) native() *C.GValue {
828	return v.GValue
829}
830
831// Native returns a pointer to the underlying GValue.
832func (v *Value) Native() uintptr {
833	return uintptr(unsafe.Pointer(v.native()))
834}
835
836// IsValue checks if value is a valid and initialized GValue structure.
837func (v *Value) IsValue() bool {
838	return gobool(C._g_is_value(v.native()))
839}
840
841// TypeName gets the type name of value.
842func (v *Value) TypeName() string {
843	return C.GoString((*C.char)(C._g_value_type_name(v.native())))
844}
845
846// ValueAlloc allocates a Value and sets a runtime finalizer to call
847// g_value_unset() on the underlying GValue after leaving scope.
848// ValueAlloc() returns a non-nil error if the allocation failed.
849func ValueAlloc() (*Value, error) {
850	c := C._g_value_alloc()
851	if c == nil {
852		return nil, nilPtrErr
853	}
854
855	v := &Value{c}
856
857	//An allocated GValue is not guaranteed to hold a value that can be unset
858	//We need to double check before unsetting, to prevent:
859	//`g_value_unset: assertion 'G_IS_VALUE (value)' failed`
860	runtime.SetFinalizer(v, func(f *Value) {
861
862		if !f.IsValue() {
863			C.g_free(C.gpointer(f.native()))
864			return
865		}
866
867		f.unset()
868	})
869
870	return v, nil
871}
872
873// ValueInit is a wrapper around g_value_init() and allocates and
874// initializes a new Value with the Type t.  A runtime finalizer is set
875// to call g_value_unset() on the underlying GValue after leaving scope.
876// ValueInit() returns a non-nil error if the allocation failed.
877func ValueInit(t Type) (*Value, error) {
878	c := C._g_value_init(C.GType(t))
879	if c == nil {
880		return nil, nilPtrErr
881	}
882
883	v := &Value{c}
884
885	runtime.SetFinalizer(v, (*Value).unset)
886	return v, nil
887}
888
889// ValueFromNative returns a type-asserted pointer to the Value.
890func ValueFromNative(l unsafe.Pointer) *Value {
891	//TODO why it does not add finalizer to the value?
892	return &Value{(*C.GValue)(l)}
893}
894
895func (v *Value) unset() {
896	C.g_value_unset(v.native())
897}
898
899// Unset is wrapper for g_value_unset
900func (v *Value) Unset() {
901	v.unset()
902}
903
904// Type is a wrapper around the G_VALUE_HOLDS_GTYPE() macro and
905// the g_value_get_gtype() function.  GetType() returns TYPE_INVALID if v
906// does not hold a Type, or otherwise returns the Type of v.
907func (v *Value) Type() (actual Type, fundamental Type, err error) {
908	if !v.IsValue() {
909		return actual, fundamental, errors.New("invalid GValue")
910	}
911	cActual := C._g_value_type(v.native())
912	cFundamental := C._g_value_fundamental(cActual)
913	return Type(cActual), Type(cFundamental), nil
914}
915
916// GValue converts a Go type to a comparable GValue.  GValue()
917// returns a non-nil error if the conversion was unsuccessful.
918func GValue(v interface{}) (gvalue *Value, err error) {
919	if v == nil {
920		val, err := ValueInit(TYPE_POINTER)
921		if err != nil {
922			return nil, err
923		}
924		val.SetPointer(uintptr(unsafe.Pointer(nil)))
925		return val, nil
926	}
927
928	switch e := v.(type) {
929	case bool:
930		val, err := ValueInit(TYPE_BOOLEAN)
931		if err != nil {
932			return nil, err
933		}
934		val.SetBool(e)
935		return val, nil
936
937	case int8:
938		val, err := ValueInit(TYPE_CHAR)
939		if err != nil {
940			return nil, err
941		}
942		val.SetSChar(e)
943		return val, nil
944
945	case int64:
946		val, err := ValueInit(TYPE_INT64)
947		if err != nil {
948			return nil, err
949		}
950		val.SetInt64(e)
951		return val, nil
952
953	case int:
954		val, err := ValueInit(TYPE_INT)
955		if err != nil {
956			return nil, err
957		}
958		val.SetInt(e)
959		return val, nil
960
961	case uint8:
962		val, err := ValueInit(TYPE_UCHAR)
963		if err != nil {
964			return nil, err
965		}
966		val.SetUChar(e)
967		return val, nil
968
969	case uint64:
970		val, err := ValueInit(TYPE_UINT64)
971		if err != nil {
972			return nil, err
973		}
974		val.SetUInt64(e)
975		return val, nil
976
977	case uint:
978		val, err := ValueInit(TYPE_UINT)
979		if err != nil {
980			return nil, err
981		}
982		val.SetUInt(e)
983		return val, nil
984
985	case float32:
986		val, err := ValueInit(TYPE_FLOAT)
987		if err != nil {
988			return nil, err
989		}
990		val.SetFloat(e)
991		return val, nil
992
993	case float64:
994		val, err := ValueInit(TYPE_DOUBLE)
995		if err != nil {
996			return nil, err
997		}
998		val.SetDouble(e)
999		return val, nil
1000
1001	case string:
1002		val, err := ValueInit(TYPE_STRING)
1003		if err != nil {
1004			return nil, err
1005		}
1006		val.SetString(e)
1007		return val, nil
1008
1009	case *Object:
1010		val, err := ValueInit(TYPE_OBJECT)
1011		if err != nil {
1012			return nil, err
1013		}
1014		val.SetInstance(uintptr(unsafe.Pointer(e.GObject)))
1015		return val, nil
1016
1017	default:
1018		/* Try this since above doesn't catch constants under other types */
1019		rval := reflect.ValueOf(v)
1020		switch rval.Kind() {
1021		case reflect.Int8:
1022			val, err := ValueInit(TYPE_CHAR)
1023			if err != nil {
1024				return nil, err
1025			}
1026			val.SetSChar(int8(rval.Int()))
1027			return val, nil
1028
1029		case reflect.Int16:
1030			return nil, errors.New("Type not implemented")
1031
1032		case reflect.Int32:
1033			return nil, errors.New("Type not implemented")
1034
1035		case reflect.Int64:
1036			val, err := ValueInit(TYPE_INT64)
1037			if err != nil {
1038				return nil, err
1039			}
1040			val.SetInt64(rval.Int())
1041			return val, nil
1042
1043		case reflect.Int:
1044			val, err := ValueInit(TYPE_INT)
1045			if err != nil {
1046				return nil, err
1047			}
1048			val.SetInt(int(rval.Int()))
1049			return val, nil
1050
1051		case reflect.Uintptr, reflect.Ptr:
1052			val, err := ValueInit(TYPE_POINTER)
1053			if err != nil {
1054				return nil, err
1055			}
1056			val.SetPointer(rval.Pointer())
1057			return val, nil
1058		}
1059	}
1060
1061	return nil, errors.New("Type not implemented")
1062}
1063
1064// GValueMarshaler is a marshal function to convert a GValue into an
1065// appropriate Go type.  The uintptr parameter is a *C.GValue.
1066type GValueMarshaler func(uintptr) (interface{}, error)
1067
1068// TypeMarshaler represents an actual type and it's associated marshaler.
1069type TypeMarshaler struct {
1070	T Type
1071	F GValueMarshaler
1072}
1073
1074// RegisterGValueMarshalers adds marshalers for several types to the
1075// internal marshalers map. Once registered, calling GoValue on any
1076// Value with a registered type will return the data returned by the
1077// marshaler.
1078func RegisterGValueMarshalers(tm []TypeMarshaler) {
1079	gValueMarshalers.register(tm)
1080}
1081
1082type marshalMap map[Type]GValueMarshaler
1083
1084// gValueMarshalers is a map of Glib types to functions to marshal a
1085// GValue to a native Go type.
1086var gValueMarshalers = marshalMap{
1087	TYPE_INVALID:   marshalInvalid,
1088	TYPE_NONE:      marshalNone,
1089	TYPE_INTERFACE: marshalInterface,
1090	TYPE_CHAR:      marshalChar,
1091	TYPE_UCHAR:     marshalUchar,
1092	TYPE_BOOLEAN:   marshalBoolean,
1093	TYPE_INT:       marshalInt,
1094	TYPE_LONG:      marshalLong,
1095	TYPE_ENUM:      marshalEnum,
1096	TYPE_INT64:     marshalInt64,
1097	TYPE_UINT:      marshalUint,
1098	TYPE_ULONG:     marshalUlong,
1099	TYPE_FLAGS:     marshalFlags,
1100	TYPE_UINT64:    marshalUint64,
1101	TYPE_FLOAT:     marshalFloat,
1102	TYPE_DOUBLE:    marshalDouble,
1103	TYPE_STRING:    marshalString,
1104	TYPE_POINTER:   marshalPointer,
1105	TYPE_BOXED:     marshalBoxed,
1106	TYPE_OBJECT:    marshalObject,
1107	TYPE_VARIANT:   marshalVariant,
1108}
1109
1110func (m marshalMap) register(tm []TypeMarshaler) {
1111	for i := range tm {
1112		m[tm[i].T] = tm[i].F
1113	}
1114}
1115
1116func (m marshalMap) lookup(v *Value) (GValueMarshaler, error) {
1117	actual, fundamental, err := v.Type()
1118	if err != nil {
1119		return nil, err
1120	}
1121
1122	if f, ok := m[actual]; ok {
1123		return f, nil
1124	}
1125	if f, ok := m[fundamental]; ok {
1126		return f, nil
1127	}
1128	return nil, errors.New("missing marshaler for type")
1129}
1130
1131func (m marshalMap) lookupType(t Type) (GValueMarshaler, error) {
1132	if f, ok := m[Type(t)]; ok {
1133		return f, nil
1134	}
1135	return nil, errors.New("missing marshaler for type")
1136}
1137
1138func marshalInvalid(uintptr) (interface{}, error) {
1139	return nil, errors.New("invalid type")
1140}
1141
1142func marshalNone(uintptr) (interface{}, error) {
1143	return nil, nil
1144}
1145
1146func marshalInterface(uintptr) (interface{}, error) {
1147	return nil, errors.New("interface conversion not yet implemented")
1148}
1149
1150func marshalChar(p uintptr) (interface{}, error) {
1151	c := C.g_value_get_schar((*C.GValue)(unsafe.Pointer(p)))
1152	return int8(c), nil
1153}
1154
1155func marshalUchar(p uintptr) (interface{}, error) {
1156	c := C.g_value_get_uchar((*C.GValue)(unsafe.Pointer(p)))
1157	return uint8(c), nil
1158}
1159
1160func marshalBoolean(p uintptr) (interface{}, error) {
1161	c := C.g_value_get_boolean((*C.GValue)(unsafe.Pointer(p)))
1162	return gobool(c), nil
1163}
1164
1165func marshalInt(p uintptr) (interface{}, error) {
1166	c := C.g_value_get_int((*C.GValue)(unsafe.Pointer(p)))
1167	return int(c), nil
1168}
1169
1170func marshalLong(p uintptr) (interface{}, error) {
1171	c := C.g_value_get_long((*C.GValue)(unsafe.Pointer(p)))
1172	return int(c), nil
1173}
1174
1175func marshalEnum(p uintptr) (interface{}, error) {
1176	c := C.g_value_get_enum((*C.GValue)(unsafe.Pointer(p)))
1177	return int(c), nil
1178}
1179
1180func marshalInt64(p uintptr) (interface{}, error) {
1181	c := C.g_value_get_int64((*C.GValue)(unsafe.Pointer(p)))
1182	return int64(c), nil
1183}
1184
1185func marshalUint(p uintptr) (interface{}, error) {
1186	c := C.g_value_get_uint((*C.GValue)(unsafe.Pointer(p)))
1187	return uint(c), nil
1188}
1189
1190func marshalUlong(p uintptr) (interface{}, error) {
1191	c := C.g_value_get_ulong((*C.GValue)(unsafe.Pointer(p)))
1192	return uint(c), nil
1193}
1194
1195func marshalFlags(p uintptr) (interface{}, error) {
1196	c := C.g_value_get_flags((*C.GValue)(unsafe.Pointer(p)))
1197	return uint(c), nil
1198}
1199
1200func marshalUint64(p uintptr) (interface{}, error) {
1201	c := C.g_value_get_uint64((*C.GValue)(unsafe.Pointer(p)))
1202	return uint64(c), nil
1203}
1204
1205func marshalFloat(p uintptr) (interface{}, error) {
1206	c := C.g_value_get_float((*C.GValue)(unsafe.Pointer(p)))
1207	return float32(c), nil
1208}
1209
1210func marshalDouble(p uintptr) (interface{}, error) {
1211	c := C.g_value_get_double((*C.GValue)(unsafe.Pointer(p)))
1212	return float64(c), nil
1213}
1214
1215func marshalString(p uintptr) (interface{}, error) {
1216	c := C.g_value_get_string((*C.GValue)(unsafe.Pointer(p)))
1217	return C.GoString((*C.char)(c)), nil
1218}
1219
1220func marshalBoxed(p uintptr) (interface{}, error) {
1221	c := C.g_value_get_boxed((*C.GValue)(unsafe.Pointer(p)))
1222	return uintptr(unsafe.Pointer(c)), nil
1223}
1224
1225func marshalPointer(p uintptr) (interface{}, error) {
1226	c := C.g_value_get_pointer((*C.GValue)(unsafe.Pointer(p)))
1227	return unsafe.Pointer(c), nil
1228}
1229
1230func marshalObject(p uintptr) (interface{}, error) {
1231	c := C.g_value_get_object((*C.GValue)(unsafe.Pointer(p)))
1232	return newObject((*C.GObject)(c)), nil
1233}
1234
1235func marshalVariant(p uintptr) (interface{}, error) {
1236	c := C.g_value_get_variant((*C.GValue)(unsafe.Pointer(p)))
1237	return newVariant((*C.GVariant)(c)), nil
1238}
1239
1240// GoValue converts a Value to comparable Go type.  GoValue()
1241// returns a non-nil error if the conversion was unsuccessful.  The
1242// returned interface{} must be type asserted as the actual Go
1243// representation of the Value.
1244//
1245// This function is a wrapper around the many g_value_get_*()
1246// functions, depending on the type of the Value.
1247func (v *Value) GoValue() (interface{}, error) {
1248	f, err := gValueMarshalers.lookup(v)
1249	if err != nil {
1250		return nil, err
1251	}
1252
1253	//No need to add finalizer because it is already done by ValueAlloc and ValueInit
1254	rv, err := f(uintptr(unsafe.Pointer(v.native())))
1255	return rv, err
1256}
1257
1258// SetBool is a wrapper around g_value_set_boolean().
1259func (v *Value) SetBool(val bool) {
1260	C.g_value_set_boolean(v.native(), gbool(val))
1261}
1262
1263// SetSChar is a wrapper around g_value_set_schar().
1264func (v *Value) SetSChar(val int8) {
1265	C.g_value_set_schar(v.native(), C.gint8(val))
1266}
1267
1268// SetInt64 is a wrapper around g_value_set_int64().
1269func (v *Value) SetInt64(val int64) {
1270	C.g_value_set_int64(v.native(), C.gint64(val))
1271}
1272
1273// SetInt is a wrapper around g_value_set_int().
1274func (v *Value) SetInt(val int) {
1275	C.g_value_set_int(v.native(), C.gint(val))
1276}
1277
1278// SetUChar is a wrapper around g_value_set_uchar().
1279func (v *Value) SetUChar(val uint8) {
1280	C.g_value_set_uchar(v.native(), C.guchar(val))
1281}
1282
1283// SetUInt64 is a wrapper around g_value_set_uint64().
1284func (v *Value) SetUInt64(val uint64) {
1285	C.g_value_set_uint64(v.native(), C.guint64(val))
1286}
1287
1288// SetUInt is a wrapper around g_value_set_uint().
1289func (v *Value) SetUInt(val uint) {
1290	C.g_value_set_uint(v.native(), C.guint(val))
1291}
1292
1293// SetFloat is a wrapper around g_value_set_float().
1294func (v *Value) SetFloat(val float32) {
1295	C.g_value_set_float(v.native(), C.gfloat(val))
1296}
1297
1298// SetDouble is a wrapper around g_value_set_double().
1299func (v *Value) SetDouble(val float64) {
1300	C.g_value_set_double(v.native(), C.gdouble(val))
1301}
1302
1303// SetString is a wrapper around g_value_set_string().
1304func (v *Value) SetString(val string) {
1305	cstr := C.CString(val)
1306	defer C.free(unsafe.Pointer(cstr))
1307	C.g_value_set_string(v.native(), (*C.gchar)(cstr))
1308}
1309
1310// SetInstance is a wrapper around g_value_set_instance().
1311func (v *Value) SetInstance(instance uintptr) {
1312	C.g_value_set_instance(v.native(), C.gpointer(instance))
1313}
1314
1315// SetPointer is a wrapper around g_value_set_pointer().
1316func (v *Value) SetPointer(p uintptr) {
1317	C.g_value_set_pointer(v.native(), C.gpointer(p))
1318}
1319
1320// GetPointer is a wrapper around g_value_get_pointer().
1321func (v *Value) GetPointer() unsafe.Pointer {
1322	return unsafe.Pointer(C.g_value_get_pointer(v.native()))
1323}
1324
1325// GetString is a wrapper around g_value_get_string().  GetString()
1326// returns a non-nil error if g_value_get_string() returned a NULL
1327// pointer to distinguish between returning a NULL pointer and returning
1328// an empty string.
1329func (v *Value) GetString() (string, error) {
1330	c := C.g_value_get_string(v.native())
1331	if c == nil {
1332		return "", nilPtrErr
1333	}
1334	return C.GoString((*C.char)(c)), nil
1335}
1336
1337type Signal struct {
1338	name     string
1339	signalId C.guint
1340}
1341
1342func SignalNew(s string) (*Signal, error) {
1343	cstr := C.CString(s)
1344	defer C.free(unsafe.Pointer(cstr))
1345
1346	signalId := C._g_signal_new((*C.gchar)(cstr))
1347
1348	if signalId == 0 {
1349		return nil, fmt.Errorf("invalid signal name: %s", s)
1350	}
1351
1352	return &Signal{
1353		name:     s,
1354		signalId: signalId,
1355	}, nil
1356}
1357
1358func (s *Signal) String() string {
1359	return s.name
1360}
1361
1362type Quark uint32
1363
1364// GetPrgname is a wrapper around g_get_prgname().
1365func GetPrgname() string {
1366	c := C.g_get_prgname()
1367
1368	return C.GoString((*C.char)(c))
1369}
1370
1371// SetPrgname is a wrapper around g_set_prgname().
1372func SetPrgname(name string) {
1373	cstr := (*C.gchar)(C.CString(name))
1374	defer C.free(unsafe.Pointer(cstr))
1375
1376	C.g_set_prgname(cstr)
1377}
1378
1379// GetApplicationName is a wrapper around g_get_application_name().
1380func GetApplicationName() string {
1381	c := C.g_get_application_name()
1382
1383	return C.GoString((*C.char)(c))
1384}
1385
1386// SetApplicationName is a wrapper around g_set_application_name().
1387func SetApplicationName(name string) {
1388	cstr := (*C.gchar)(C.CString(name))
1389	defer C.free(unsafe.Pointer(cstr))
1390
1391	C.g_set_application_name(cstr)
1392}
1393
1394// InitI18n initializes the i18n subsystem.
1395func InitI18n(domain string, dir string) {
1396	domainStr := C.CString(domain)
1397	defer C.free(unsafe.Pointer(domainStr))
1398
1399	dirStr := C.CString(dir)
1400	defer C.free(unsafe.Pointer(dirStr))
1401
1402	C.init_i18n(domainStr, dirStr)
1403}
1404
1405// Local localizes a string using gettext
1406func Local(input string) string {
1407	cstr := C.CString(input)
1408	defer C.free(unsafe.Pointer(cstr))
1409
1410	return C.GoString(C.localize(cstr))
1411}
1412