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

desktop

module
v0.20.1 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: BSD-3-Clause

README

desktop

ci Go Reference Go 1.26.4 License BSD-3-Clause

A native, pure-Go (CGO=0) desktop-shell demo that composes the whole go-freedesktop + go-widgets stack into one runnable app. Each freedesktop library does its real job against a real Linux filesystem, and the UI is drawn entirely with go-widgets widgets and box layouts.

What each library drives

Feature Library What it does here
Dock + launcher go-freedesktop/desktopentry Scan() → the app index; ExpandExec → launch argv
Icons go-freedesktop/icontheme FindIcon → PNG/JPEG rasterized into go-widgets Image
Application menu go-freedesktop/menu Load() → a categorized tree rendered as a go-widgets MenuBar/Menu
"Open with" go-freedesktop/mime + mimeapps TypeByNameAndContent + Candidates/DefaultApp
File grid + thumbnails toolkit/virtual VirtualGrid + go-thumbnail virtualized gengrid over a directory, thumbnail cache keys per cell
Notifications go-freedesktop/notifications a live org.freedesktop.Notifications daemon → go-widgets Toasts

Architecture

Composition/model logic is separated from raw rendering:

  • shell/ — pure, side-effect-light model logic with 100% statement coverage (including error branches): the launchable-app index, MIME "open with" resolution, the categorized menu model, the directory listing model and the thumbnail cache-key policy. No rendering surface, so every branch is unit-coverable against temp-dir fixtures.
  • render/ — turns those models into a go-widgets widget tree. The shell is a Border layout (menubar north, dock south, launcher west, file grid center) plus a floating Toast stack. State flows through go-widgets/mvvm (Observable search query → ObservableList results → the launcher). Scene.Widget() wraps the whole thing — root plus the toast overlay — as one backend-agnostic toolkit.Widget a windowing backend can drive.
  • cmd/desktop/ — the native binary: scans the filesystem, composes the scene and either opens a real window (the default) or renders it to a PNG (-capture).
  • source/ — the two shell.AppSource implementations behind the shell (see below).
  • clients/desktop/ — the wasmdesk client (js/wasm): the exact same shell composed from the embedded source and presented to the wasmdesk compositor. It opens its surface through the same window.Open() the native binary uses — on js/wasm that returns go-widgets/window's wasmbox client backend, so there is one windowing code path, native and browser (no desktop-local backend to maintain).

Same source, two targets

The shell's data is abstracted behind one seam, shell.AppSource: installed apps, the categorized menu, the directory listing, "open with" resolution, icon bytes and thumbnail keys. There are two implementations in source/, and render.New composes the identical Scene from either:

Target Source Data Backend
Native (Linux desktop) source.NewXDG real XDG filesystem (desktopentry.Scan, icontheme, mime/mimeapps, menu.Load, go-thumbnail) go-widgets/window (X11/Wayland)
Browser (wasmdesk) source.NewEmbedded a curated app set + icons + virtual files from an embed.FS — no filesystem go-widgets/window (wasmbox client)

So the browser desktop is not a mock: it is the same shell model logic, the same render widget tree, AND the same window.Open()/Backend.Run() windowing path as the native binary — only source.NewXDG→source.NewEmbedded differs. The wasmbox client wire (hello/welcome/commit/input over the compositor's MessagePort + SharedArrayBuffer) lives entirely inside go-widgets/window, so this repo hosts no duplicate backend.

Primary browser proof — the REAL wasmdesk desktop. The shell runs as a genuine external client of the actual wasmdesk/wasmbox Ruby compositor (the pure-Go rbgo interpreter running compositor/*.rb, baked into wasmbox.wasm), spawned via the documented globalThis.wasmboxSpawnExternal(...) hook and served same-origin through a symlink overlay — the wasmbox repository is never modified. Playwright locates the window by its live focused rect (__wasmboxFocusedRect), asserts the shell (dock, launcher, application menu, file grid) rendered into the composited desktop, and round-trips one real click. See clients/desktop/harness/probe-real-desktop.mjs and clients/desktop/harness/README-real-desktop.md:

desktop shell as a real external client of the wasmdesk Ruby desktop

Deterministic CI floor. The protocol-faithful harness (clients/desktop/harness) drives the identical wire/SAB/input assertions with no Ruby compositor build, so it gates anywhere:

desktop shell as a wasmdesk client in the browser

go-widgets is a pure pixel-blitting toolkit. With no flags the shell opens a real window on the running display server via go-widgets/window — which auto-selects the pure-Go Wayland backend when $WAYLAND_DISPLAY is set, else the pure-Go X11 backend — and drives the widget tree through its Run loop (resize → relayout, window close → quit). Notification toasts render as a floating overlay on top of the live shell. On a headless host, or with -capture, the shell renders into an offscreen framebuffer and -capture writes it to a PNG — the headless "screenshot" path.

Below is the live X11 window (under Xvfb) showing the dock, launcher, file grid and a notification Toast — the live shell (windowed) CI lane captures and pixel-asserts exactly this:

live desktop shell in a real X11 window

Usage

go run ./cmd/desktop                                        # open a real window (X11/Wayland)
go run ./cmd/desktop -dir ~/Pictures                        # windowed, file grid on a directory
go run ./cmd/desktop -dir ~/Pictures -capture shell.png     # headless: render to PNG
go run ./cmd/desktop -query fire                            # seed launcher filter
go run ./cmd/desktop -launch org.mozilla.firefox            # expand Exec + launch
go run ./cmd/desktop -embedded -capture browser.png         # the exact scene the wasmdesk client shows

# Browser (wasmdesk) client:
GOOS=js GOARCH=wasm go build -o desktop.wasm ./clients/desktop   # build the wasm client
clients/desktop/harness/run.sh                                   # prove it in a real headless browser

# Notifications need a session bus (Linux); the toast shows in the window:
dbus-run-session -- go run ./cmd/desktop -notify "Build|Finished"
dbus-run-session -- go run ./cmd/desktop -notify "Build|Finished" -capture toast.png

License

BSD-3-Clause. Copyright (c) 2026 the go-widgets/desktop authors.

Directories

Path Synopsis
clients
desktop command
cmd
desktop command
Package render turns the shell package's composition/model values into a live go-widgets widget tree and captures it to an image.
Package render turns the shell package's composition/model values into a live go-widgets widget tree and captures it to an image.
Package shell holds the pure composition/model logic of the desktop shell: the launchable-app index, MIME "open with" resolution, the categorized application-menu model, the directory listing model and the thumbnail cache-key derivation.
Package shell holds the pure composition/model logic of the desktop shell: the launchable-app index, MIME "open with" resolution, the categorized application-menu model, the directory listing model and the thumbnail cache-key derivation.
Package source provides the two concrete shell.AppSource implementations that feed the desktop shell: the native xdgSource (source_xdg.go, !js), which scans a real XDG filesystem, and the embeddedSource (this file), which serves a curated app set, icon set and virtual file listing from an embed.FS.
Package source provides the two concrete shell.AppSource implementations that feed the desktop shell: the native xdgSource (source_xdg.go, !js), which scans a real XDG filesystem, and the embeddedSource (this file), which serves a curated app set, icon set and virtual file listing from an embed.FS.

Jump to

Keyboard shortcuts

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