Add sovereign pure-Go Wayland backend with X11/Wayland auto-select - #2
Merged
Conversation
From-scratch, pure-Go (CGO=0, zero non-stdlib dep) Wayland wire protocol, mirroring the internal/x11 sovereign transport+codec approach. - wire.go: message framing + typed-arg codec (int/uint/fixed 24.8/string/ array/object/new_id), native-order parametrised for the s390x big-endian lane; bounds-checked decoder. - transport.go: UNIX-socket transport with SCM_RIGHTS fd passing via net.UnixConn WriteMsgUnix/ReadMsgUnix (no cgo), stream reassembly, fd queue; injectable control-parser seam for full error-branch coverage. - conn.go: object table + dispatcher, wl_display (sync/get_registry, error+ delete_id), wl_callback, wl_registry global enumeration + bind, Roundtrip. Table round-trip tests (both endian paths) incl fd args and every error branch; real socketpair + scripted fake-compositor + stub transport. internal/wayland coverage: 100.0%. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- surface.go: wl_compositor bind + create_surface; wl_surface attach/damage/ damage_buffer/commit/frame(throttle callback)/destroy. - shm.go: portable anonymous shm (open+unlink+ftruncate+mmap, no memfd dep, cross-platform so it unit-tests on macOS too); wl_shm bind + format enumeration; wl_shm_pool.create_pool (fd over SCM_RIGHTS) + create_buffer ARGB8888; wl_buffer release tracking; injectable syscall seams for full error-branch coverage. - xdgshell.go: xdg_wm_base (auto ping->pong) + get_xdg_surface; xdg_surface configure->ack; xdg_toplevel set_title/set_app_id + configure(size)/close. - present.go: RGBA->ARGB8888 native-order packing; Registry bind helpers. internal/wayland coverage: 100.0%; race-clean; 6-arch cross-compile. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
internal/wayland: - seat.go: wl_seat (capabilities/name) -> wl_pointer (enter/leave/motion/ button/axis) + wl_keyboard (keymap-over-fd, key, modifiers, repeat_info), callback-delivered; injectable mmap seam for the keymap fd. - xkb.go: from-scratch xkb_v1 keymap parser (keycodes + symbols sections) -> keysym name -> rune / toolkit key name; minimal-but-functional table (letters/digits/punctuation/navigation/modifiers), documented scope. window (backend-agnostic): - Backend interface; X11 *Window and the new *wlWindow both satisfy it. - wlwindow.go: full xdg-shell bring-up, double-buffered wl_shm present (RGBA->ARGB8888), pure event->toolkit translation (100%), resize/close, ping/pong, shared Run host loop. - open_linux.go: Open auto-selects Wayland when $WAYLAND_DISPLAY is set, else X11; non-linux stub returns ErrUnsupported (Backend). Tests: internal/wayland 100% (incl xkb parse, seat/pointer/keyboard event decode, keymap-fd mmap, every error branch); pure event->toolkit mapping 100%; in-process scripted fake-compositor drives the whole handshake + click + key end to end. race-clean; 6-arch cross-compile. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Extend the 100% coverage gate to internal/wayland alongside internal/x11. - Add the live-wayland CI lane: launch a headless wlroots compositor (sway), open a real xdg-shell toplevel via the sovereign backend, present a known four-quadrant pattern through wl_shm, capture with grim and assert sampled pixels; best-effort key injection via wtype (virtual-keyboard), honestly skipped when the headless seat exposes no keyboard. - Scope the X11 live lane to TestLiveX11; the 6-arch matrix already runs the whole module, so s390x exercises the Wayland wire codec big-endian path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The os.TempDir() fallback in createAnonFile is only taken when XDG_RUNTIME_DIR is unset (true on macOS, false on Linux/CI), so the race coverage gate saw 99.9% on the Linux runner. Exercise both the unset (TempDir) and set branches explicitly so internal/wayland is a deterministic 100% on every host. Verified 100% under -race on linux/arm64. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an owned, pure-Go, CGO=0, zero-non-stdlib-dependency Wayland backend to
go-widgets/window, implementing the Wayland wire protocol from scratch over theUNIX socket — the same sovereign approach as the existing
internal/x11backendand
go-freedesktop/dbus.window.Open()now auto-selects the backend: Waylandwhen
$WAYLAND_DISPLAYis set, else X11. The X11 backend is unchanged and fullyworking.
Dated artifact: horodate 2026-08-08 22:21 CEST.
Phases
internal/wayland/wire.go,transport.go,conn.go): message framing (object-id / opcode / size) and the full typed-argcodec (int/uint/fixed 24.8/string/array/object/new_id); object-id allocator;
wl_display(sync/get_registry, error + delete_id),wl_registryglobalenumeration + bind;
Roundtrip. fd passing via SCM_RIGHTS overnet.UnixConnWriteMsgUnix/ReadMsgUnix+syscall.UnixRights— no cgo.Native-order codec parametrised so the s390x lane exercises big-endian.
surface.go,shm.go,xdgshell.go,present.go):wl_compositor,wl_shm, stablexdg_wm_base/xdg_surface/xdg_toplevel; portable anonymous shm (open+unlink+ftruncate+mmap) →create_pool(fd over SCM_RIGHTS) → ARGB8888
create_buffer; RGBA→ARGB pack, attach/damage/commit, double-buffer, frame-throttle callback,
xdg_wm_base.ping→pong,configure→ack.
seat.go,xkb.go,wlwindow.go):wl_seat→wl_pointer(enter/leave/motion/button/axis) +wl_keyboard(keymap over anxkb_v1 shared-memory fd → parsed → keycode→keysym→rune / toolkit key name);
modifiers/repeat; close + disconnect. All wired into the shared
Run(root)host loop via a new
Backendinterface satisfied by both*Window(X11) and*wlWindow.Auto-select
Open(Config) (Backend, error): Wayland when$WAYLAND_DISPLAYis set (socketresolved against
$XDG_RUNTIME_DIR), else X11 via$DISPLAY. Non-Linux stubreturns
ErrUnsupported. A go-widgets app is backend-agnostic (Run/Size/Close/String).Tests & CI
internal/waylandcoverage: 100.0% incl every error branch — wire codec(both endian paths, fd args), registry, shm-pool math, xkb keymap parse,
seat/pointer/keyboard event decode (keymap-fd mmap), and the pure
event→toolkit mapping (100%). Real socketpair + scripted fake compositor +
stub transport.
a click + a key end to end (deterministic, no display server).
sway(wlroots) → open a real toplevel,present a four-quadrant pattern via wl_shm, capture with
grim, assert sampledpixels; best-effort key via
wtype, honestly skipped when the headless seatexposes no keyboard.
6-arch CGO=0 matrix (s390x big-endian wire codec),
-race, darwin stub.🤖 Generated with Claude Code