Go bindings for libghostty-vt.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 242 lines 7.2 kB view raw
1package libghostty 2 3// System-level configuration wrapping ghostty_sys_set(). 4// These are process-global settings that must be configured at startup. 5 6/* 7#include <ghostty/vt.h> 8#include <ghostty/vt/sys.h> 9 10// Forward declaration for the Go log trampoline so we can take its 11// address on the C side. Uses compatible types (no const, int for enum) 12// to match what cgo generates for the //export function. 13extern void goSysLogTrampoline( 14 void* userdata, 15 int level, 16 uint8_t* scope, 17 size_t scope_len, 18 uint8_t* message, 19 size_t message_len); 20 21// Forward declaration for the Go decode-PNG trampoline. 22// Uses compatible types (no const) to match what cgo generates for 23// the //export function. 24extern _Bool goSysDecodePngTrampoline( 25 void* userdata, 26 GhosttyAllocator* allocator, 27 uint8_t* data, 28 size_t data_len, 29 GhosttySysImage* out); 30 31// Helper to install the Go log trampoline via ghostty_sys_set. 32// We need this because cgo cannot take the address of a Go-exported 33// function directly as a C function pointer. 34static inline GhosttyResult sys_set_log_go(void) { 35 return ghostty_sys_set(GHOSTTY_SYS_OPT_LOG, (const void*)goSysLogTrampoline); 36} 37 38// Helper to install the built-in stderr log callback. 39static inline GhosttyResult sys_set_log_stderr(void) { 40 return ghostty_sys_set(GHOSTTY_SYS_OPT_LOG, (const void*)ghostty_sys_log_stderr); 41} 42 43// Helper to clear the log callback. 44static inline GhosttyResult sys_clear_log(void) { 45 return ghostty_sys_set(GHOSTTY_SYS_OPT_LOG, NULL); 46} 47 48// Helper to install the Go decode-PNG trampoline via ghostty_sys_set. 49static inline GhosttyResult sys_set_decode_png_go(void) { 50 return ghostty_sys_set(GHOSTTY_SYS_OPT_DECODE_PNG, (const void*)goSysDecodePngTrampoline); 51} 52 53// Helper to clear the decode-PNG callback. 54static inline GhosttyResult sys_clear_decode_png(void) { 55 return ghostty_sys_set(GHOSTTY_SYS_OPT_DECODE_PNG, NULL); 56} 57*/ 58import "C" 59 60import "unsafe" 61 62// SysImage holds the result of decoding an image (e.g. PNG) into raw 63// RGBA pixel data. Returned by the user-supplied decode callback. 64// C: GhosttySysImage 65type SysImage struct { 66 // Width of the decoded image in pixels. 67 Width uint32 68 69 // Height of the decoded image in pixels. 70 Height uint32 71 72 // Data is the decoded RGBA pixel data (4 bytes per pixel). 73 Data []byte 74} 75 76// SysDecodePngFn is the Go callback type for PNG decoding. It receives 77// raw PNG data and must return a decoded SysImage. The returned pixel 78// data will be copied into library-managed memory; the caller does not 79// need to keep the slice alive after returning. 80// 81// Return a non-nil error to indicate decode failure. 82// C: GhosttySysDecodePngFn 83type SysDecodePngFn func(data []byte) (*SysImage, error) 84 85// sysDecodePngFn is the currently installed Go decode-PNG callback. 86var sysDecodePngFn SysDecodePngFn 87 88// SysSetDecodePng installs a Go callback that decodes PNG image data 89// into RGBA pixels. This enables PNG support in the Kitty Graphics 90// Protocol. Pass nil to clear the callback and disable PNG decoding. 91// 92// This function is not safe for concurrent use. Callers must ensure 93// that decode configuration is not modified while terminals may 94// process image data (e.g. configure at startup before creating 95// terminals). 96func SysSetDecodePng(fn SysDecodePngFn) error { 97 sysDecodePngFn = fn 98 if fn == nil { 99 return resultError(C.sys_clear_decode_png()) 100 } 101 return resultError(C.sys_set_decode_png_go()) 102} 103 104// SysLogLevel represents the severity level of a log message from the 105// library. Maps directly to the C enum values. 106// C: GhosttySysLogLevel 107type SysLogLevel int 108 109const ( 110 // SysLogLevelError is the error log level. 111 SysLogLevelError SysLogLevel = C.GHOSTTY_SYS_LOG_LEVEL_ERROR 112 113 // SysLogLevelWarning is the warning log level. 114 SysLogLevelWarning SysLogLevel = C.GHOSTTY_SYS_LOG_LEVEL_WARNING 115 116 // SysLogLevelInfo is the info log level. 117 SysLogLevelInfo SysLogLevel = C.GHOSTTY_SYS_LOG_LEVEL_INFO 118 119 // SysLogLevelDebug is the debug log level. 120 SysLogLevelDebug SysLogLevel = C.GHOSTTY_SYS_LOG_LEVEL_DEBUG 121) 122 123// String returns a human-readable name for the log level. 124func (l SysLogLevel) String() string { 125 switch l { 126 case SysLogLevelError: 127 return "error" 128 case SysLogLevelWarning: 129 return "warning" 130 case SysLogLevelInfo: 131 return "info" 132 case SysLogLevelDebug: 133 return "debug" 134 default: 135 return "unknown" 136 } 137} 138 139// SysLogFn is the Go callback type for log messages from the library. 140// The scope identifies the subsystem (e.g. "osc", "kitty"); it is 141// empty for unscoped (default) log messages. The message and scope 142// are only valid for the duration of the call. 143// C: GhosttySysLogFn 144type SysLogFn func(level SysLogLevel, scope string, message string) 145 146// sysLogFn is the currently installed Go log callback. 147var sysLogFn SysLogFn 148 149// SysSetLog installs a Go callback that receives internal library log 150// messages. Pass nil to clear the callback and discard log messages. 151// 152// Which log levels are emitted depends on the build mode of the 153// library. Debug builds emit all levels; release builds emit info 154// and above. 155// 156// This function is not safe for concurrent use. Callers must ensure 157// that log configuration is not modified while log messages may be 158// delivered (e.g. configure at startup before creating terminals). 159func SysSetLog(fn SysLogFn) error { 160 sysLogFn = fn 161 if fn == nil { 162 return resultError(C.sys_clear_log()) 163 } 164 return resultError(C.sys_set_log_go()) 165} 166 167// SysSetLogStderr installs the built-in stderr log callback provided 168// by libghostty. Each message is formatted as "[level](scope): message\n" 169// and written to stderr in a thread-safe manner. 170// 171// This function is not safe for concurrent use. See [SysSetLog]. 172func SysSetLogStderr() error { 173 sysLogFn = nil 174 return resultError(C.sys_set_log_stderr()) 175} 176 177//export goSysLogTrampoline 178func goSysLogTrampoline( 179 _ unsafe.Pointer, 180 level C.int, 181 scopePtr *C.uint8_t, 182 scopeLen C.size_t, 183 messagePtr *C.uint8_t, 184 messageLen C.size_t, 185) { 186 fn := sysLogFn 187 if fn == nil { 188 return 189 } 190 191 var scope string 192 if scopeLen > 0 { 193 scope = C.GoStringN((*C.char)(unsafe.Pointer(scopePtr)), C.int(scopeLen)) 194 } 195 196 var message string 197 if messageLen > 0 { 198 message = C.GoStringN((*C.char)(unsafe.Pointer(messagePtr)), C.int(messageLen)) 199 } 200 201 fn(SysLogLevel(level), scope, message) 202} 203 204//export goSysDecodePngTrampoline 205func goSysDecodePngTrampoline( 206 _ unsafe.Pointer, 207 allocator *C.GhosttyAllocator, 208 dataPtr *C.uint8_t, 209 dataLen C.size_t, 210 out *C.GhosttySysImage, 211) C.bool { 212 fn := sysDecodePngFn 213 if fn == nil { 214 return false 215 } 216 217 // Build a Go slice over the input PNG data without copying. 218 data := unsafe.Slice((*byte)(unsafe.Pointer(dataPtr)), int(dataLen)) 219 220 img, err := fn(data) 221 if err != nil || img == nil { 222 return false 223 } 224 225 // Allocate output pixel buffer through the library's allocator so 226 // the library can free it later. 227 pixelLen := C.size_t(len(img.Data)) 228 buf := C.ghostty_alloc(allocator, pixelLen) 229 if buf == nil { 230 return false 231 } 232 233 // Copy decoded pixels into the library-owned buffer. 234 copy(unsafe.Slice((*byte)(unsafe.Pointer(buf)), int(pixelLen)), img.Data) 235 236 out.width = C.uint32_t(img.Width) 237 out.height = C.uint32_t(img.Height) 238 out.data = buf 239 out.data_len = pixelLen 240 241 return true 242}