Skip to content
Native window

A native window

go-widgets/window: one Open/Run API over X11, Wayland, GTK4, Cocoa, Win32, Android, wasmbox and a browser tab, all with CGO_ENABLED=0.

go-widgets/window opens a real window and runs a widget tree in it: layout, draw, present, translate input into toolkit.Event, repeat until the window closes.

w, err := window.Open(window.Config{Title: "Demo"})
if err != nil {
	return err
}
defer w.Close()
return w.Run(root) // root is any toolkit.Widget

Config also takes the initial size in logical points (zero asks for a readable default), the WM_CLASS instance and class, a Theme, and a RenderScale.

How Open chooses

Platform and environmentBack-endHow it reaches the screen
Linux, $GO_WIDGETS_GTK setGTK4GTK owns the window; the framebuffer is a GtkPicture, and native controls are real GTK widgets above it. Needs the libgtk-4 runtime.
Linux, $WAYLAND_DISPLAY setWaylandxdg-shell over the compositor’s unix socket
Linux, otherwise $DISPLAYX11the X11 core protocol over the unix socket, with MIT-SHM
macOSCocoaNSWindow and NSView through go-macos/objc (purego)
WindowsWin32a top-level HWND through user32 and gdi32 syscalls, StretchDIBits
Android, $GW_ANDROID_SOCKET setAndroid hosta framed protocol to the Java host, pixels in a shared memfd
Android, otherwiseWayland or X11a shell under Termux still has a display server to dial
js/wasm, inside wasmdeskwasmboxa client of the wasmdesk compositor
js/wasm, an ordinary pagebrowser taba <canvas> of the page (Config.Canvas, default "screen") through webcanvas: no compositor, no SharedArrayBuffer, no cross-origin isolation
anything else—window.ErrUnsupported, so a cross-build still compiles

Every back-end is CGO_ENABLED=0. The X11 one is the core protocol written from scratch over the socket — no Xlib, no XCB — with both byte orders, the Xauthority cookie, keysym mapping, PutImage tiled under the server’s request size, and the MIT-SHM fast path, the shared segment passed over SCM_RIGHTS. Windows is reached through the process’s own DLLs with syscall.NewLazyDLL and a syscall.NewCallback window procedure; macOS through the Objective-C runtime with purego.

The platform-independent part of each back-end — event mapping, coordinate maths, pixel packing, damage rectangles — lives in a codec covered at 100%, on every operating system. The thin platform glue is proven live: see Status.

Only what changed

A root that implements DamageRenderer (as toolkit/scene.HostRoot does) reports the rectangles it repainted, and every back-end but GTK4 presents only those: X11 through MIT-SHM ShmPutImage, Wayland through wl_shm damage, Cocoa, Win32, Android, wasmbox and the browser tab. The first frame, a resize and an X11 Expose still present the whole surface.

HiDPI

The default is one framebuffer pixel per logical point: the UI is laid out and painted at a readable size, and the compositor up-samples it. On Windows the window declares per-monitor DPI awareness and the OS scales the logical frame to the physical client area. RenderScale asks for a framebuffer at the panel’s real resolution, which is correct only for a root that lays out in device pixels.

Screens, and showing and hiding

window.Screens() lists the attached displays, primary first, in logical points with the desktop’s panels excluded, and may be called before Open. A screen’s name is the panel’s own ("DELL U2720Q", from its EDID), falling back to the connector ("HDMI-1") when it publishes none — and also when two attached panels publish the same one, since a name that cannot tell them apart is not a name.

window.Show, Hide and Raise take an open window off the screen without closing it and bring it back — what a tray application needs.

Back-endShowHideRaise
X11MapWindowICCCM withdraw, so it leaves the taskbarmap, raise, _NET_ACTIVE_WINDOW
Waylandcommit againnull buffer and commitErrNotSupported: xdg-shell has no such request
macOSorderFront:orderOut:activate the app, makeKeyAndOrderFront:
WindowsSW_SHOWNASW_HIDESW_RESTORE and SetForegroundWindow
GTK, Android, wasmbox, browser tabErrNotSupportedErrNotSupportedErrNotSupported

Focus is the platform’s to grant: under focus-stealing prevention, Raise may only mark the window as wanting attention, and cannot tell.

Created on by tannevaled

Modified on by tannevaled