Help us shape the future of Go! Take the 2026 Go Developer Survey

xkbcommon

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 10 Imported by: 0

README

purego-xkbcommon

Go 1.27 bindings for Linux libxkbcommon.so.0, without cgo or X11. The safe package owns native references; the raw package exposes generated ABI constants, types, and function bindings. Install libxkbcommon at runtime and xkeyboard-config for rules-based keymaps. The loader reports missing libraries and required symbols via Available.

ctx, err := xkbcommon.NewContext()
if err != nil { return err }
defer ctx.Close()
keymap, err := ctx.NewKeymapRules("evdev", "pc105", "fr", "", "")
if err != nil { return err }
defer keymap.Close()
state, err := keymap.NewState()
if err != nil { return err }
defer state.Close()
text, err := state.UTF8(xkbcommon.WaylandKeycode(evdevKeycode))

Use NewKeymapFD(fd, size) for Wayland xkb_v1 keymaps; it copies exactly size bytes with pread (at most 16 MiB), fails on a short read, and accepts an optional trailing NUL. The caller retains and must close the FD, on success and failure. UpdateMask accepts Wayland modifier masks and group indices. ComposeState.Feed and Status distinguish composing, composed, cancelled, and ignored keysyms; use UTF8 only for a composed result. Objects retain their native parents; close each object, in any order. Do not copy value structs containing a mutex.

State.UTF8Into and ComposeState.UTF8Into write into a caller-owned buffer of 1..MaxUTF8Buffer bytes and create no Go string. On io.ErrShortBuffer the whole buffer is wiped and n+1 bytes are needed; the caller wipes the buffer after use.

Pinned upstream headers and licenses are in upstream/; upstream/METADATA and SHA256SUMS identify their exact source. Run GOWORK=off go generate ./... to regenerate raw/generated.go; consumers do not run generation. The generator checks the selected ABI declarations against the headers. github.com/bnema/purego v0.13.0-bnema.1 matches purego-vulkan and supports Dlopen, Dlsym, and the fixed-arity Syscall6/Syscall15 with cgo disabled.

Allocation-free hot path

raw.Funcs holds symbol addresses resolved once by Available; every generated method calls purego.Syscall6 (or Syscall15 for more than six arguments) directly, so no reflection or return boxing happens per call. Per-key calls — State.KeySym, State.UTF8Into, State.UpdateMask, State.Layout, State.Mods, State.ModIndexActive, State.ModNameActive, Keymap.KeyRepeats, KeysymNameInto and the ComposeState Feed/Status/KeySym/UTF8Into/Reset methods — perform 0 allocations (asserted by TestHotPathAllocs). The *Into methods stay allocation-free only with a long-lived dst reused across calls: a buffer passed to C escapes, so a fresh local array costs one allocation per call. The string-returning UTF8 and KeysymName still allocate their result.

v0.2.0: raw API change

Only the raw package changed incompatibly; the root xkbcommon package is source-compatible (it gains State.ModNameActive, State.ModIndexActive, Keymap.KeyRepeats and KeysymNameInto).

  • raw.Funcs fields are no longer func values. Each function is now a method with the same exported name (f.Xkb_state_key_get_one_sym(...)), and the struct holds unexported symbol addresses.
  • Pointer parameters (strings, buffers, *RuleNames) are unsafe.Pointer instead of uintptr, and RuleNames fields are unsafe.Pointer. Pass the pointer directly; never pre-convert it to uintptr, which would not keep the memory alive.
  • raw.Register(f, addresses, register) is now raw.Register(f, addresses); there is no purego.RegisterFunc hook.
  • A zero raw.Funcs is unusable: calling any method panics (purego: fn is nil) until Register has filled it. xkbcommon.Available does this for the package's own loader.
  • The generator only accepts uintptr, uint32, int32 and unsafe.Pointer parameters and uintptr, uint32, int32 or no return value, and rejects floats, bools and varargs.

Documentation

Overview

Package xkbcommon interprets Wayland keyboard maps with libxkbcommon, loaded at runtime without cgo. Close owned values when they are no longer used.

Index

Constants

View Source
const MaxUTF8Buffer = 512

MaxUTF8Buffer is the byte API's maximum scratch length, including the native trailing NUL. Thus a full result can contain at most 511 payload bytes.

Variables

View Source
var ErrClosed = errors.New("xkbcommon: closed handle")
View Source
var ErrUTF8Buffer = fmt.Errorf("xkbcommon: UTF-8 buffer length must be 1..%d", MaxUTF8Buffer)

ErrUTF8Buffer reports a destination buffer whose length is outside 1..MaxUTF8Buffer.

Functions

func Available

func Available() error

Available resolves the SONAME and every required symbol, reporting the first incompatible symbol rather than failing later in a keyboard event callback.

func KeysymFromName

func KeysymFromName(name string) (uint32, error)

func KeysymName

func KeysymName(sym uint32) (string, error)

func KeysymNameInto added in v0.2.0

func KeysymNameInto(sym uint32, dst []byte) (int, error)

KeysymNameInto writes the keysym name into dst without allocating, with the same bounds and short-buffer semantics as State.UTF8Into.

func WaylandKeycode

func WaylandKeycode(evdev uint32) uint32

Keycodes from wl_keyboard are evdev codes; add 8 before calling State.KeySym or State.UTF8.

Types

type ComposeState

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

func (*ComposeState) Close

func (s *ComposeState) Close() error

func (*ComposeState) Feed

func (s *ComposeState) Feed(sym uint32) (uint32, error)

func (*ComposeState) KeySym

func (s *ComposeState) KeySym() (uint32, error)

func (*ComposeState) Reset

func (s *ComposeState) Reset() error

func (*ComposeState) Status

func (s *ComposeState) Status() (uint32, error)

func (*ComposeState) UTF8

func (s *ComposeState) UTF8() (string, error)

func (*ComposeState) UTF8Into

func (s *ComposeState) UTF8Into(dst []byte) (int, error)

UTF8Into is the compose counterpart of State.UTF8Into, with identical bounds, ownership, NUL and short-buffer semantics. It does not reset compose.

type ComposeTable

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

func (*ComposeTable) Close

func (t *ComposeTable) Close() error

func (*ComposeTable) NewState

func (t *ComposeTable) NewState() (*ComposeState, error)

type Context

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

func NewContext

func NewContext() (*Context, error)

func (*Context) Close

func (c *Context) Close() error

func (*Context) NewComposeTable

func (c *Context) NewComposeTable(locale string) (*ComposeTable, error)

func (*Context) NewKeymapFD

func (c *Context) NewKeymapFD(fd int, size int) (*Keymap, error)

NewKeymapFD copies exactly size bytes from offset zero of a Wayland xkb_v1 keymap FD (at most 16 MiB). A trailing Wayland NUL, if present, is excluded from the compiled text. The caller retains ownership of fd, even on error.

func (*Context) NewKeymapRules

func (c *Context) NewKeymapRules(rules, model, layout, variant, options string) (*Keymap, error)

NewKeymapRules compiles an evdev rules keymap. Empty rules/model/variant/options use libxkbcommon defaults; layout is e.g. "us", "fr", "de", or "us,de".

func (*Context) NewKeymapString

func (c *Context) NewKeymapString(text string) (*Keymap, error)

NewKeymapString compiles a NUL-free xkb_v1 text keymap.

type Keymap

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

func (*Keymap) Close

func (k *Keymap) Close() error

func (*Keymap) KeyRepeats added in v0.2.0

func (k *Keymap) KeyRepeats(keycode uint32) (bool, error)

KeyRepeats reports whether the key repeats when held. It does not allocate.

func (*Keymap) LayoutCount

func (k *Keymap) LayoutCount() (uint32, error)

func (*Keymap) ModIndex

func (k *Keymap) ModIndex(name string) (uint32, error)

func (*Keymap) NewState

func (k *Keymap) NewState() (*State, error)

type State

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

func (*State) Close

func (s *State) Close() error

func (*State) KeySym

func (s *State) KeySym(keycode uint32) (uint32, error)

func (*State) Layout

func (s *State) Layout() (uint32, error)

func (*State) ModIndexActive added in v0.2.0

func (s *State) ModIndexActive(idx uint32) (bool, error)

ModIndexActive reports whether the modifier at idx is effectively active. It does not allocate. An unknown index reports false.

func (*State) ModNameActive added in v0.2.0

func (s *State) ModNameActive(name string) (bool, error)

ModNameActive reports whether the named modifier (for example raw.XKB_MOD_NAME_CTRL) is effectively active. Names up to 63 bytes do not allocate. An unknown name reports false.

func (*State) Mods

func (s *State) Mods() (uint32, error)

func (*State) UTF8

func (s *State) UTF8(keycode uint32) (string, error)

func (*State) UTF8Into

func (s *State) UTF8Into(keycode uint32, dst []byte) (int, error)

UTF8Into writes into caller-owned mutable storage without constructing a string. dst is passed to C through a uintptr-escaping call, so its backing array lives on the heap (a stack array sliced into dst is moved there once). n excludes NUL; on io.ErrShortBuffer n is the required payload size, all of dst is cleared, and the caller needs n+1 bytes. dst must have length 1..MaxUTF8Buffer. No storage is retained; the caller owns wiping after use.

func (*State) UpdateMask

func (s *State) UpdateMask(depressed, latched, locked, groupDepressed, groupLatched, groupLocked uint32) (uint32, error)

UpdateMask accepts depressed/latched/locked modifier masks and layout group indices in the order supplied by wl_keyboard.modifiers. It returns changed components.

Directories

Path Synopsis
cmd
xkbgen command
internal
gen
Package gen generates the deliberately bounded libxkbcommon ABI subset.
Package gen generates the deliberately bounded libxkbcommon ABI subset.
Code generated by go generate; DO NOT EDIT.
Code generated by go generate; DO NOT EDIT.

Jump to

Keyboard shortcuts

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