slint

package module
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 21, 2026 License: MIT Imports: 7 Imported by: 0

README

go-slint (wip)

Go bindings for the Slint declarative UI toolkit. Write your UI in .slint, generate a typed Go API from it, and drive it with compile-checked methods.

⚠️ The majority of this repository was generated by an LLM. Review it and use at your own risk it has not yet been used in production.

// app.slint
export component AppWindow inherits Window {
    in-out property <int> counter: 0;
    callback clicked();
}
// main.go  (//go:generate goslint generate -o ui/app.slint.go app.slint)
win, _ := ui.NewAppWindow()
defer win.Close()

win.OnClicked(func() {
    n, _ := win.Counter()
    _ = win.SetCounter(n + 1)
})
win.Run()

Property and callback names are real Go methods. Structs and enums become Go types, arrays become []T, and imported .slint files are embedded — so even a multi-file UI builds into one self-contained binary. A lower-level dynamic API is also available for compiling .slint at runtime. → See the Guide.

Quickstart

You need Go and a C compiler for cgo — gcc/clang on Linux, the Xcode command-line tools on macOS, MinGW-w64 gcc on Windows (not MSVC). You do not need Rust or pkg-config; the native Slint library is downloaded prebuilt. Run goslint doctor to check your toolchain.

go install github.com/rileylov/go-slint/cmd/goslint@latest

goslint init myapp     # scaffold go.mod + app.slint + main.go + ui/
cd myapp
goslint setup          # download the native lib matching your go.mod
goslint dev .          # run; edit app.slint or .go → auto-regenerate & reload

Ship it:

goslint build -o myapp .                # one self-contained desktop binary
goslint android build -o myapp.apk .    # signed APK (arm64-v8a + x86_64)

goslint is the whole interface: init, setup, generate, dev, build, run, android, doctor, uninstall. Full walkthrough in the Guide.

Platforms

Platform Status
Linux (amd64, arm64) ✅ tested
Android (arm64-v8a, x86_64) ✅ tested
Windows (amd64) ⚠️ builds with MinGW-w64 gcc; rendering not yet verified on hardware
macOS, iOS ❌ (no hardware to test on)

Desktop targets link libgoslint (and the Slint interpreter) statically, leaving only ubiquitous system libraries — on Linux, OpenGL and fontconfig (the fontconfig dev package is also needed at build time).

Documentation

  • Guide (DOCS.md) — step-by-step: properties, callbacks, globals, structs, enums, arrays, models, the dynamic API, and shipping.
  • Architecture (CLAUDE.md) — the three layers, building the shim from source, and tracking upstream Slint (make update-slint).
  • Examples — runnable typed and dynamic apps.

License

The go-slint binding code here is MIT.

go-slint links the Slint toolkit, which is separately licensed and not covered by this repository's MIT license. Slint is tri-licensed:

  • GPLv3 — free, your app must be GPL-compatible;
  • a royalty-free license for desktop/mobile/web apps — free, with a "Made with Slint" attribution; this covers all of go-slint's supported targets;
  • a commercial license — paid; removes attribution.

Any app you build with go-slint, and the prebuilt libgoslint binaries in Releases (which embed Slint), are governed by Slint's license — choose and comply with one of the options above. See LICENSES for details.

Documentation

Overview

Package slint provides Go bindings for the Slint declarative UI toolkit.

UIs are written in Slint's .slint markup language and driven from Go. This package compiles .slint markup at runtime (via Slint's interpreter), creates component instances, and lets you read and write properties, handle callbacks, back models, load images, and run timers — all from Go.

Threading

Slint is thread-affine. Compile, Create, property/callback access, and Run must all happen on a single OS thread. Lock it at program start:

func init() { runtime.LockOSThread() }

To touch the UI from another goroutine, post work with InvokeFromEventLoop.

A minimal program

package main

import (
	_ "embed"
	"runtime"

	"github.com/rileylov/go-slint"
)

func init() { runtime.LockOSThread() }

//go:embed app.slint
var ui string

func main() {
	app, err := slint.Compile(ui, slint.WithStyle("fluent"))
	if err != nil {
		panic(err)
	}
	defer app.Close()

	win, err := app.Create("AppWindow")
	if err != nil {
		panic(err)
	}
	defer win.Close()

	win.OnCallback("clicked", func([]any) any {
		n, _ := win.Int("counter")
		win.Set("counter", n+1)
		return nil
	})
	win.Run()
}

Value mapping

Properties and callback arguments/returns convert between Slint and Go as:

void                          <-> nil
int / float / length / angle  <-> float64
bool                          <-> bool
string                        <-> string
struct / anonymous object     <-> map[string]any
enum                          <-> [Enum]{Type, Value}
color / solid brush           <-> [Color]
gradient brush                <-> [Gradient] (linear or radial)
image                         <-> *[Image] (write; load via [LoadImage])
array / model                 <-> []any (read) or [*ModelHandle] (write)

Build a writable model with NewSliceModel (or NewModel for a custom Model) and assign it to an array/model property; mutating it notifies Slint.

See the cmd/examples directory for runnable apps (hello, counter, todo, clock, interop, chartstress) and CLAUDE.md for the architecture.

The package overview lives in doc.go.

Index

Constants

View Source
const (
	TimerSingleShot = slintsys.TimerSingleShot
	TimerRepeated   = slintsys.TimerRepeated
)

Timer modes.

Variables

This section is empty.

Functions

func InitHeadless

func InitHeadless() error

InitHeadless installs the headless testing backend (mock time, no real windows). Intended for tests; call once per process on the UI thread.

func InvokeFromEventLoop

func InvokeFromEventLoop(fn func()) error

InvokeFromEventLoop posts fn to run once on the event-loop (UI) thread. Safe to call from any goroutine; it is the only safe way to touch UI state (properties, models, callbacks) from a background goroutine.

func LiveReload

func LiveReload(path, component string, bind func(*Instance) error, opts ...Option) error

LiveReload compiles the .slint file at path, creates component (or the last exported one if component is ""), wires it with bind, shows it, and then hot-reloads whenever any .slint file beside it changes on disk — recompiling and swapping the window in place, with no Go rebuild. It runs the event loop and returns when the window is closed.

It's the engine behind `goslint dev`: because the interpreter loads markup at runtime, editing a .slint and saving updates the UI live. bind is re-invoked on each reload with the fresh instance, so wire your callbacks/properties there (note: property state resets on reload). Call runtime.LockOSThread first, as with any Slint program.

func MockElapsedTime

func MockElapsedTime(ms uint64)

MockElapsedTime advances the headless backend's mock clock by ms milliseconds.

func Quit

func Quit() error

Quit asks the running event loop to exit.

func Run

func Run() error

Run enters the Slint event loop until the last window closes or Quit is called. It blocks and must run on the UI thread.

func SingleShot

func SingleShot(intervalMs uint64, fn func())

SingleShot fires fn once after the given number of milliseconds.

func Version

func Version() string

Version returns the Slint version these bindings were built against.

Types

type Callback

type Callback = slintsys.CallbackFunc

Callback is a Go handler invoked by Slint. Its args and return use the same Go value representation as properties (float64, bool, string, map[string]any, Enum, nil, ...).

type Color

type Color = slintsys.Color

Color is an RGBA color (a `color` property, or a solid `brush`).

type Compilation

type Compilation struct {
	// contains filtered or unexported fields
}

Compilation is a successfully compiled set of components.

func Compile

func Compile(source string, opts ...Option) (*Compilation, error)

Compile compiles `.slint` source. It returns a *DiagnosticError if the source has errors.

func CompileFile

func CompileFile(path string, opts ...Option) (*Compilation, error)

CompileFile compiles a `.slint` file from disk.

func CompileSource added in v0.3.0

func CompileSource(path, source string, opts ...Option) (*Compilation, error)

CompileSource compiles markup from a string while treating it as if it lived at `path`, so relative imports (and @image-url) resolve from path's directory on disk. Generated typed code uses this so multi-file components work; for a single embedded file with no relative imports, plain Compile is enough.

func (*Compilation) Close

func (c *Compilation) Close()

Close releases the compilation's resources.

func (*Compilation) ComponentNames

func (c *Compilation) ComponentNames() []string

ComponentNames lists the exported components.

func (*Compilation) Create

func (c *Compilation) Create(name string) (*Instance, error)

Create instantiates the named component.

type DiagnosticError

type DiagnosticError struct {
	Diagnostics []slintsys.Diagnostic
}

DiagnosticError reports one or more compiler errors.

func (*DiagnosticError) Error

func (e *DiagnosticError) Error() string

type Enum

type Enum = slintsys.Enum

Enum is the Go representation of a Slint enumeration value (e.g. Enum{Type: "TextHorizontalAlignment", Value: "center"}). Structs are represented as map[string]any.

type FileLoader added in v0.3.0

type FileLoader = slintsys.FileLoader

FileLoader resolves a `.slint` import path to source; ok=false means "not found" (normal include-path/disk resolution then proceeds). Builtins like std-widgets are handled internally and never passed to it.

type Gradient added in v0.2.0

type Gradient = slintsys.Gradient

Gradient is a gradient `brush` value (linear by default, or Radial); set it on a brush/color property, or read one back from Get. GradientStop is one stop.

type GradientStop added in v0.2.0

type GradientStop = slintsys.GradientStop

GradientStop is one stop of a Gradient: Pos in 0..=1 with a Color.

type Image

type Image = slintsys.Image

Image is a loaded image; assign it to an `image` property and Free it when done.

func LoadImage

func LoadImage(path string) (*Image, error)

LoadImage loads an image (PNG/JPEG) from a file path.

type Instance

type Instance struct {
	// contains filtered or unexported fields
}

Instance is a live component instance.

func (*Instance) Bool

func (i *Instance) Bool(name string) (bool, error)

Bool reads a boolean property.

func (*Instance) Close

func (i *Instance) Close()

Close releases the instance.

func (*Instance) Float

func (i *Instance) Float(name string) (float64, error)

Float reads a numeric property.

func (*Instance) Get

func (i *Instance) Get(name string) (any, error)

Get reads a property as a Go value (float64, bool, string, or nil).

func (*Instance) GetGlobal

func (i *Instance) GetGlobal(global, name string) (any, error)

GetGlobal reads a property of an exported global singleton.

func (*Instance) Hide

func (i *Instance) Hide() error

func (*Instance) Int

func (i *Instance) Int(name string) (int, error)

Int reads a numeric property as an int.

func (*Instance) Invoke

func (i *Instance) Invoke(name string, args ...any) (any, error)

Invoke calls a callback or function, returning its result (nil for void).

func (*Instance) InvokeGlobal

func (i *Instance) InvokeGlobal(global, name string, args ...any) (any, error)

InvokeGlobal calls a callback or function on an exported global.

func (*Instance) OnCallback

func (i *Instance) OnCallback(name string, fn Callback) error

OnCallback installs a handler for the named callback.

func (*Instance) OnGlobalCallback

func (i *Instance) OnGlobalCallback(global, name string, fn Callback) error

OnGlobalCallback installs a handler for a callback on an exported global.

func (*Instance) RequestRedraw added in v0.2.0

func (i *Instance) RequestRedraw()

func (*Instance) Run

func (i *Instance) Run() error

func (*Instance) ScaleFactor added in v0.2.0

func (i *Instance) ScaleFactor() float32

func (*Instance) Set

func (i *Instance) Set(name string, v any) error

Set writes a property from a Go value.

func (*Instance) SetFullscreen added in v0.2.0

func (i *Instance) SetFullscreen(on bool)

func (*Instance) SetGlobal

func (i *Instance) SetGlobal(global, name string, v any) error

SetGlobal writes a property of an exported global singleton.

func (*Instance) SetMaximized added in v0.2.0

func (i *Instance) SetMaximized(on bool)

func (*Instance) SetMinimized added in v0.2.0

func (i *Instance) SetMinimized(on bool)

func (*Instance) SetWindowPosition added in v0.2.0

func (i *Instance) SetWindowPosition(x, y int)

func (*Instance) SetWindowSize added in v0.2.0

func (i *Instance) SetWindowSize(w, h int)

func (*Instance) Show

func (i *Instance) Show() error

Show makes the window visible. Hide hides it. Run shows then runs the loop.

func (*Instance) Str

func (i *Instance) Str(name string) (string, error)

Str reads a string property.

func (*Instance) WindowPosition added in v0.2.0

func (i *Instance) WindowPosition() (x, y int)

func (*Instance) WindowSize added in v0.2.0

func (i *Instance) WindowSize() (w, h int)

Window control. Sizes and positions are in physical pixels; divide by ScaleFactor to get logical (.slint) pixels. These act on the instance's window and are most reliable once it's shown.

Note: on Wayland the compositor controls window placement, so SetWindowPosition/WindowPosition are no-ops there (they work on X11, Windows, and macOS). Run on X11 — e.g. with WAYLAND_DISPLAY unset — to use positioning.

type Model

type Model = slintsys.Model

Model is a data source backing a Slint model property / `for` loop.

type ModelHandle

type ModelHandle = slintsys.ModelHandle

ModelHandle binds a Model for use as a property value; report data changes via its Notify* methods. Obtain one with NewModel or SliceModel.Handle.

func NewModel

func NewModel(m Model) *ModelHandle

NewModel binds a custom Model implementation so it can be assigned to a property.

type Option

type Option func(*slintsys.Compiler)

Option configures a compilation.

func WithFileLoader added in v0.3.0

func WithFileLoader(fn FileLoader) Option

WithFileLoader installs a fallback resolver for `.slint` imports, letting a multi-file component compile entirely from in-memory source (no files on disk). Generated typed code uses this to embed every imported file.

func WithIncludePaths

func WithIncludePaths(paths ...string) Option

WithIncludePaths sets the paths used to resolve `.slint` imports.

func WithLibraryPaths added in v0.2.0

func WithLibraryPaths(libs map[string]string) Option

WithLibraryPaths maps `@library` import names to their paths, e.g. WithLibraryPaths(map[string]string{"mylib": "./libs/mylib"}) resolves `import { Foo } from "@mylib/foo.slint"`.

func WithStyle

func WithStyle(style string) Option

WithStyle selects the widget style (e.g. "fluent", "material", "cupertino"). Required for `.slint` files that import "std-widgets.slint".

type SliceModel

type SliceModel struct {
	// contains filtered or unexported fields
}

SliceModel is a built-in slice-backed Model whose mutators auto-notify Slint.

func NewSliceModel

func NewSliceModel(items ...any) *SliceModel

NewSliceModel creates a slice-backed model from the given items.

func (*SliceModel) Append

func (s *SliceModel) Append(v any)

Append adds an item and notifies Slint.

func (*SliceModel) Close

func (s *SliceModel) Close()

Close releases the model's binding handle.

func (*SliceModel) Handle

func (s *SliceModel) Handle() *ModelHandle

Handle returns the binding handle (also accepted directly by property setters).

func (*SliceModel) Len

func (s *SliceModel) Len() int

Len reports the number of rows.

func (*SliceModel) RemoveAt

func (s *SliceModel) RemoveAt(row int)

RemoveAt removes the item at row and notifies Slint.

func (*SliceModel) RowCount

func (s *SliceModel) RowCount() int

func (*SliceModel) RowData

func (s *SliceModel) RowData(row int) any

func (*SliceModel) SetRowData

func (s *SliceModel) SetRowData(row int, v any)

type Timer

type Timer = slintsys.Timer

Timer fires a Go callback after an interval. Timers fire only while the event loop runs (Run); create and start them after Create.

func NewTimer

func NewTimer() *Timer

NewTimer creates a stopped timer.

Directories

Path Synopsis
cmd
examples/chartstress command
Shared throughput-harness logic for desktop (main.go) and Android (app_android.go).
Shared throughput-harness logic for desktop (main.go) and Android (app_android.go).
examples/clock command
Command clock is an interactive go-slint example using the TYPED API: a repeating Timer driven from Go updates the typed `ticks` property once a second.
Command clock is an interactive go-slint example using the TYPED API: a repeating Timer driven from Go updates the typed `ticks` property once a second.
examples/counter command
Command counter is an interactive go-slint example using the TYPED API (generated by `goslint generate` — see the directive).
Command counter is an interactive go-slint example using the TYPED API (generated by `goslint generate` — see the directive).
examples/gradient command
Command gradient demonstrates building gradient brushes in Go (slint.Gradient) and assigning them to a `brush` property: linear at various angles, radial, a multi-stop rainbow, and an animated rotating gradient driven by a timer.
Command gradient demonstrates building gradient brushes in Go (slint.Gradient) and assigning them to a `brush` property: linear at various angles, radial, a multi-stop rainbow, and an animated rotating gradient driven by a timer.
examples/hello command
Command hello shows a minimal Slint window from Go.
Command hello shows a minimal Slint window from Go.
examples/interop command
Shared Go ⇄ Slint interop logic, used by both the desktop entry (main.go) and the Android entry (app_android.go).
Shared Go ⇄ Slint interop logic, used by both the desktop entry (main.go) and the Android entry (app_android.go).
examples/multifile command
Command multifile is a TYPED example whose .slint imports another .slint (components/card.slint).
Command multifile is a TYPED example whose .slint imports another .slint (components/card.slint).
examples/todo command
Command todo is an interactive go-slint example showing a live model: a Go SliceModel backs the list, and add/delete are handled in Go.
Command todo is an interactive go-slint example showing a live model: a Go SliceModel backs the list, and add/delete are handled in Go.
examples/typed command
Command typed is the hello example using the TYPED API generated by `goslint generate` (see the //go:generate directive).
Command typed is the hello example using the TYPED API generated by `goslint generate` (see the //go:generate directive).
examples/window command
Command window demonstrates Go-side window control: resizing, positioning, maximize/fullscreen, plus reading back size/position/scale-factor.
Command window demonstrates Go-side window control: resizing, positioning, maximize/fullscreen, plus reading back size/position/scale-factor.
goslint command
Command goslint provisions the native Slint shim library for the go-slint bindings and wraps `go build`/`go run` with the right linker configuration.
Command goslint provisions the native Slint shim library for the go-slint bindings and wraps `go build`/`go run` with the right linker configuration.
goslint-gen command
Command goslint-gen generates a typed Go API from a .slint file.
Command goslint-gen generates a typed Go API from a .slint file.
Package slintsys is the low-level cgo binding to the goslint-sys C ABI (Layer 1).
Package slintsys is the low-level cgo binding to the goslint-sys C ABI (Layer 1).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL