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