nefergui

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2026 License: GPL-3.0 Imports: 2 Imported by: 0

README

NeferGUI

A native Go GUI library for Linux: Wayland windows, Vulkan rendering, and CSS styling. Build your view from the current model; controls return events during that call. No cgo required.

[!WARNING] Early development. No release yet. Expect bugs and breaking changes. Platform accessibility is not connected.

A small example

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/bnema/nefergui"
)

func main() {
	count := 0
	view := func(f *nefergui.Frame, count *int) {
		root := f.Root().Column()
		root.Text("Hello, Wayland!")
		if root.Button("Count", nefergui.Key("count")).Activated() {
			*count++
		}
		root.Text(fmt.Sprintf("Clicked %d times", *count))
	}
	if err := nefergui.Run(context.Background(), &count, view,
		nefergui.Title("Hello"), nefergui.Size(320, 200)); err != nil {
		log.Fatal(err)
	}
}

Default styles work without a stylesheet; nefergui.Styles("app.css") loads your own CSS.

Try it

Requires Go 1.27, libvulkan.so.1, libxkbcommon.so.0, usable fonts, and a Wayland compositor supporting linux-dmabuf and linux-drm-syncobj. Fractional scaling also requires viewporter. No X11 or software-rendering fallback.

go get github.com/bnema/nefergui

From a checkout, run the demo:

CGO_ENABLED=0 go run ./examples/demo

Documentation

License

GNU GPL v3. Third-party code and test fonts retain their own licenses and attribution.

Documentation

Overview

Package nefergui provides a pure-Go immediate-mode GUI for Wayland, rendered with Vulkan and styled with a bounded CSS dialect (see docs/css.md).

Run opens a window and calls the view function to build each frame. The view receives a Frame; Frame and its Node handles are valid only during that call. Key identifies a child among its siblings across frames; without a key, position and type determine identity. ID is CSS metadata, not frame identity. Options such as Title, Size, Styles and Transparent configure the window.

The frame tree, controls, editors and input routing are implemented in internal/ui; this package is the public facade and re-exports those types.

Builds support CGO_ENABLED=0. At runtime, NeferGUI requires libvulkan.so.1, libxkbcommon.so.0 and a Wayland compositor supporting linux-dmabuf and linux-drm-syncobj. See docs/runtime.md and docs/troubleshooting.md.

Example (CompileOnly)

The product-design example. Run needs a Wayland session, so this example is compiled but not executed by go test; examples/demo runs it.

package main

import (
	"context"

	"github.com/bnema/nefergui"
)

func main() {
	type Model struct {
		Page, Name, Status string
		DarkMode           bool
	}
	model := Model{Page: "home", Status: "Prêt"}
	navButton := func(parent nefergui.Node, m *Model, label, page string) {
		opts := []nefergui.ButtonOption{nefergui.Key(page), nefergui.Class("menu-item")}
		if m.Page == page {
			opts = append(opts, nefergui.Class("active"))
		}
		if parent.Button(label, opts...).Activated() {
			m.Page = page
		}
	}
	home := func(parent nefergui.Node, m *Model) {
		section := parent.Section(nefergui.Class("welcome"))
		section.Heading("Bienvenue", nefergui.Level(2))
		section.Text("Une interface native écrite entièrement en Go.")
		section.Input("Votre nom", &m.Name, nefergui.Key("name"), nefergui.Placeholder("Ada"))
		actions := section.Row(nefergui.Class("actions"))
		if actions.Button("Continuer", nefergui.Key("continue"), nefergui.Class("primary"), nefergui.Disabled(m.Name == "")).Activated() {
			m.Status = "Bonjour " + m.Name
		}
	}
	app := func(f *nefergui.Frame, m *Model) {
		root := f.Root(nefergui.Class("app"))
		header := root.Header(nefergui.Class("header"))
		header.Heading("Demo", nefergui.Level(1), nefergui.Class("logo"))
		menu := header.Nav(nefergui.Class("menu"))
		navButton(menu, m, "Accueil", "home")
		navButton(menu, m, "Paramètres", "settings")
		header.Checkbox("Thème sombre", &m.DarkMode, nefergui.Key("dark-mode"))
		content := root.Main(nefergui.Class("content"))
		switch m.Page {
		case "home":
			home(content, m)
		case "settings":
			home(content, m)
		}
		root.Footer(nefergui.Class("status-bar")).Text(m.Status)
	}
	_ = nefergui.Run(context.Background(), &model, app, nefergui.Title("Demo"), nefergui.Size(960, 640), nefergui.Styles("app.css"))
}
Example (Counter)

The README counter. Run needs a Wayland session, so this example is compiled but not executed by go test.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/bnema/nefergui"
)

func main() {
	count := 0
	view := func(f *nefergui.Frame, count *int) {
		root := f.Root().Column()
		root.Text("Hello, Wayland!")
		if root.Button("Count", nefergui.Key("count")).Activated() {
			*count++
		}
		root.Text(fmt.Sprintf("Clicked %d times", *count))
	}
	if err := nefergui.Run(context.Background(), &count, view,
		nefergui.Title("Hello"), nefergui.Size(320, 200)); err != nil {
		log.Fatal(err)
	}
}

Index

Examples

Constants

View Source
const (
	LayerBackground = ui.LayerBackground
	LayerBottom     = ui.LayerBottom
	LayerTop        = ui.LayerTop
	LayerOverlay    = ui.LayerOverlay

	AnchorTop    = ui.AnchorTop
	AnchorBottom = ui.AnchorBottom
	AnchorLeft   = ui.AnchorLeft
	AnchorRight  = ui.AnchorRight

	KeyboardNone      = ui.KeyboardNone
	KeyboardExclusive = ui.KeyboardExclusive
	KeyboardOnDemand  = ui.KeyboardOnDemand

	InputPointerMotion  = ui.InputPointerMotion
	InputPointerPress   = ui.InputPointerPress
	InputPointerRelease = ui.InputPointerRelease
	InputPointerAxis    = ui.InputPointerAxis
	InputPointerLeave   = ui.InputPointerLeave
	InputKey            = ui.InputKey
	InputFocusIn        = ui.InputFocusIn
	InputFocusOut       = ui.InputFocusOut
	InputReset          = ui.InputReset

	ModShift = ui.ModShift
	ModCtrl  = ui.ModCtrl
)

Variables

This section is empty.

Functions

func Class

func Class(class string) commonOption

Class adds a CSS class.

func Disabled

func Disabled(v bool) disabledOption

Disabled blocks focus and interaction on an interactive control.

func ID

func ID(id string) commonOption

ID sets the CSS ID; it does not affect frame identity.

func Inline

func Inline(src string) commonOption

Inline applies inline CSS declarations.

func Key

func Key(key string) commonOption

Key identifies an element among its siblings across frames.

func Run

func Run[T any](ctx context.Context, model *T, view func(*Frame, *T), options ...WindowOption) error

Run builds and presents an immediate view on the Wayland session owner loop.

func RunFrames

func RunFrames[T any](ctx context.Context, frames int, model *T, view func(*Frame, *T), committed func(uint64) error, options ...WindowOption) error

RunFrames is a deterministic harness entry: each commit requests a redraw and the loop stops after the given number of committed frames.

Types

type Anchor added in v0.2.0

type Anchor = ui.Anchor

Layer surface, input and wake configuration. Layer selects a wlr-layer-shell surface instead of an xdg toplevel; OnInput, OnResize and Wake integrate callers that own state outside the view. See internal/ui for details.

type ButtonEvent

type ButtonEvent = ui.ButtonEvent

ButtonEvent is an immutable snapshot queried with Activated. Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.ButtonEvent.

type ButtonOption

type ButtonOption = ui.ButtonOption

Option families are sealed: ContainerOption, ButtonOption, EditOption, ValueOption and HeadingOption accept the common CSS options (Key, ID, Class, Inline) plus the control-specific options listed on each function.

type ChangeEvent

type ChangeEvent = ui.ChangeEvent

ChangeEvent is an immutable snapshot queried with Changed. Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.ChangeEvent.

type ContainerOption

type ContainerOption = ui.ContainerOption

Option families are sealed: ContainerOption, ButtonOption, EditOption, ValueOption and HeadingOption accept the common CSS options (Key, ID, Class, Inline) plus the control-specific options listed on each function.

type EditEvent

type EditEvent = ui.EditEvent

EditEvent is an immutable snapshot queried with Changed and Submitted. Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.EditEvent.

type EditOption

type EditOption = ui.EditOption

Option families are sealed: ContainerOption, ButtonOption, EditOption, ValueOption and HeadingOption accept the common CSS options (Key, ID, Class, Inline) plus the control-specific options listed on each function.

func Password

func Password(v bool) EditOption

Password masks displayed editor text and blocks copy and cut.

func Placeholder

func Placeholder(v string) EditOption

Placeholder sets the text shown in an empty editor.

type Frame

type Frame = ui.Frame

Frame is valid only during one call to the view function. Root builds the application element; Diagnostics reports identity problems in debug builds. Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.Frame.

type HeadingOption

type HeadingOption = ui.HeadingOption

Option families are sealed: ContainerOption, ButtonOption, EditOption, ValueOption and HeadingOption accept the common CSS options (Key, ID, Class, Inline) plus the control-specific options listed on each function.

func Level

func Level(level int) HeadingOption

Level sets the accessibility heading level (1 through 6).

type InputEvent added in v0.2.0

type InputEvent = ui.InputEvent

Layer surface, input and wake configuration. Layer selects a wlr-layer-shell surface instead of an xdg toplevel; OnInput, OnResize and Wake integrate callers that own state outside the view. See internal/ui for details.

type InputKind added in v0.2.0

type InputKind = ui.InputKind

Layer surface, input and wake configuration. Layer selects a wlr-layer-shell surface instead of an xdg toplevel; OnInput, OnResize and Wake integrate callers that own state outside the view. See internal/ui for details.

type KeyboardMode added in v0.2.0

type KeyboardMode = ui.KeyboardMode

Layer surface, input and wake configuration. Layer selects a wlr-layer-shell surface instead of an xdg toplevel; OnInput, OnResize and Wake integrate callers that own state outside the view. See internal/ui for details.

type LayerConfig added in v0.2.0

type LayerConfig = ui.LayerConfig

Layer surface, input and wake configuration. Layer selects a wlr-layer-shell surface instead of an xdg toplevel; OnInput, OnResize and Wake integrate callers that own state outside the view. See internal/ui for details.

type LayerLevel added in v0.2.0

type LayerLevel = ui.LayerLevel

Layer surface, input and wake configuration. Layer selects a wlr-layer-shell surface instead of an xdg toplevel; OnInput, OnResize and Wake integrate callers that own state outside the view. See internal/ui for details.

type Modifiers added in v0.2.0

type Modifiers = ui.Modifiers

Layer surface, input and wake configuration. Layer selects a wlr-layer-shell surface instead of an xdg toplevel; OnInput, OnResize and Wake integrate callers that own state outside the view. See internal/ui for details.

type Node

type Node = ui.Node

Node is an ephemeral handle into the current frame. Do not retain it between frames. Container methods (Box, Row, Column, Stack, Scroll, Header, Nav, Main, Section, Aside, Footer, Element) return child nodes; control methods (Button, Checkbox, Radio, Slider, Input, Textarea, Text, Heading, Image, Icon, Separator, Spacer) declare controls. Interactive controls return event snapshots. Alias methods are listed by go doc github.com/bnema/nefergui/internal/ui.Node.

type Rect added in v0.2.0

type Rect = ui.Rect

Layer surface, input and wake configuration. Layer selects a wlr-layer-shell surface instead of an xdg toplevel; OnInput, OnResize and Wake integrate callers that own state outside the view. See internal/ui for details.

type ValueOption

type ValueOption = ui.ValueOption

Option families are sealed: ContainerOption, ButtonOption, EditOption, ValueOption and HeadingOption accept the common CSS options (Key, ID, Class, Inline) plus the control-specific options listed on each function.

type WaylandSurface added in v0.2.0

type WaylandSurface = ui.WaylandSurface

WaylandSurface is the window's Wayland display and wl_surface for OnSurface.

type WindowOption

type WindowOption = ui.WindowOption

Option families are sealed: ContainerOption, ButtonOption, EditOption, ValueOption and HeadingOption accept the common CSS options (Key, ID, Class, Inline) plus the control-specific options listed on each function.

func Layer added in v0.2.0

func Layer(c LayerConfig) WindowOption

Layer makes the window a layer-shell surface.

func OnInput added in v0.2.0

func OnInput(fn func(InputEvent) bool) WindowOption

OnInput receives raw input on the owner loop before control routing; return true to request a redraw.

func OnResize added in v0.2.0

func OnResize(fn func(width, height int, scale float64)) WindowOption

OnResize reports logical size and scale at start and on change only.

func OnSurface added in v0.2.0

func OnSurface(fn func(context.Context, WaylandSurface) error) WindowOption

OnSurface runs fn once after the surface role is configured and before the first buffer; an error aborts Run.

func Size

func Size(w, h int) WindowOption

Size sets the initial logical window size.

func Styles

func Styles(s string) WindowOption

Styles loads an author stylesheet from a file path.

func Title

func Title(s string) WindowOption

Title sets the window title.

func Transparent

func Transparent() WindowOption

Transparent requests an alpha-capable Wayland surface (opaque by default).

func Wake added in v0.2.0

func Wake(ch <-chan struct{}) WindowOption

Wake requests a redraw for each value received on ch.

Directories

Path Synopsis
cmd
examples
demo command
rect command
Rect exercises presentation directly, without the immediate API.
Rect exercises presentation directly, without the immediate API.
internal
bidi
Package bidi contains functionality for bidirectional text support.
Package bidi contains functionality for bidirectional text support.
css
edit
Package edit owns headless, grapheme-safe text state.
Package edit owns headless, grapheme-safe text state.
image
Package image provides bounded standard-library raster image ingestion.
Package image provides bounded standard-library raster image ingestion.
keyboard
Package keyboard interprets Wayland evdev key events on the UI loop.
Package keyboard interprets Wayland evdev key events on the UI loop.
layout
Package layout computes logical-pixel boxes and an ordered, serializable paint list.
Package layout computes logical-pixel boxes and an ordered, serializable paint list.
platform/wayland
Package wayland owns the minimal xdg-shell window and presentation protocol objects.
Package wayland owns the minimal xdg-shell window and presentation protocol objects.
platform/wayland/layershell
Package layershell contains local typed bindings for wlr-layer-shell v1.
Package layershell contains local typed bindings for wlr-layer-shell v1.
presentation/buffers
Package buffers models Wayland/Vulkan buffer ownership without GPU dependencies.
Package buffers models Wayland/Vulkan buffer ownership without GPU dependencies.
presentation/session
Package session coordinates Wayland ownership, Vulkan submissions, DRM release points and the application frame loop behind nefergui.Run.
Package session coordinates Wayland ownership, Vulkan submissions, DRM release points and the application frame loop behind nefergui.Run.
presentation/shaders
Package shaders owns the committed SPIR-V compiled from its sibling GLSL sources.
Package shaders owns the committed SPIR-V compiled from its sibling GLSL sources.
presentation/syncobj
Package syncobj bridges Vulkan SYNC_FD semaphores and Wayland DRM syncobj timelines on the compositor-selected render node.
Package syncobj bridges Vulkan SYNC_FD semaphores and Wayland DRM syncobj timelines on the compositor-selected render node.
presentation/vkdevice
Package vkdevice selects a Vulkan graphics device by compositor-advertised DRM dev_t.
Package vkdevice selects a Vulkan graphics device by compositor-advertised DRM dev_t.
render
Package render prepares ordered physical-pixel primitives for Vulkan submission.
Package render prepares ordered physical-pixel primitives for Vulkan submission.
text
Package text implements CPU-side font selection, shaping, measurement and grayscale glyph preparation.
Package text implements CPU-side font selection, shaping, measurement and grayscale glyph preparation.
ui
Package ui owns the immediate-mode frame tree, controls, editors, input routing and the Wayland run loop behind the public nefergui facade.
Package ui owns the immediate-mode frame tree, controls, editors, input routing and the Wayland run loop behind the public nefergui facade.

Jump to

Keyboard shortcuts

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