Wayland client support for the Jai programming language.
Built with Jai
beta 0.2.029(compiler built 25 April 2026) — the most recent version everything here was compiled and tested against.A note on paths: some code and documentation reference a hard-coded path to the unpacked Jai distribution,
~/jai/jai— but that's just where I unpacked mine. Please update this path in your clone/fork (inbuild.shand throughout the docs) to point to your own distribution.
This library takes the same approach as zig-wayland and wayland-rs: bypass libwayland-client.so entirely and speak the Wayland wire protocol directly.
Key decisions:
- No libwayland dependency. The Wayland wire protocol is simple — structured messages over a Unix socket with fd passing via
sendmsg/recvmsg. No reason to link a C library for that. - No hard-linked shared objects. Like many OpenGL and Vulkan loaders, we use function pointer tables populated at runtime via
dlopen. Nothing shows up underldd. - Code generation from protocol XML. Wayland protocols are defined in XML files. We parse them and generate Jai bindings — interface structs, opcode constants, and dispatch tables.
- Compile-time marshalling. Request functions use a compile-time
marshalmacro that walks arg struct types viatype_infoand emits specialized serialization code. Zero runtime reflection, zero branches — just raw stores.
Phase 1 (complete): XML parser and protocol data model.
- Zero-copy pull parser for XML (~290 lines)
- Protocol data model:
Protocol,Interface,Message,Arg,Enum_Def,Entry - Parses all 59 vendored protocol XML files (189 interfaces) with zero failures
Phase 2 (complete): Code generator — emit Jai source from parsed protocols.
- Standalone tool reads protocol XML and emits idiomatic Jai source files
- Per-interface files with typed structs, opcode constants, event tagged unions, enum definitions, and request functions
- Full protocol descriptions as doc comments for traceability to the spec
- 56 protocols, 175 interfaces in
modules/wayland/ - 92 tests across 5 test suites
Phase 3 (complete): Wire protocol — message framing, compile-time marshalling, fd passing.
inlineprimitive writers for native-endian 4-byte-aligned wire encodingmarshal/unmarshalmacros:#expand+#insert #run generate_marshal_code(type_info(T))— walk arg struct fields at compile time, emit type-specific (de)serialization codemarshal_constructorvariant: caller provides pre-allocated object ID, writes it as first argFd :: #type,distinct s32— file descriptors tagged for the compile-time walker, routed toSCM_RIGHTSout-of-band- Split types:
Connection(socket + ID allocator),MessageBuilder(outgoing batch, string-builder pattern),ReceiveBuffer(incoming).sendmsg/recvmsgwithSCM_RIGHTSancillary data. - Object ID allocator (client IDs from 1, incrementing, monotonic-on-wire)
- Generated request functions call
marshal()/marshal_constructor()targeting*MessageBuilder
Phase 4 (complete): Client API — no inversion of control, full input + windowing.
- Design principle: simple things MUST be simple. Application owns the event loop. No callbacks, no dispatch tables, no event queues, no proxy lifecycle manager.
WaylandSession— holdsConnection,ReceiveBuffer, bound globals (compositor, wm_base); lives in#add_context wayland_session: *WaylandSession.for session()for-expansion yieldsWaylandMessageHeaderand transparently handles ping/pong +wl_display.error.- Global discovery:
discover_globals()performswl_display.get_registry+ sync roundtrip and returns all compositor globals. Type registry for automatic version negotiation inwl_registry_bind. - Screen discovery:
get_screens_info()— binds everywl_output, returns[] Screen_Infowith modes, scale, geometry. - Seat-based input:
get_seats_info()→get_keyboards_info(seats)+get_pointers_info(seats).get_keyboard_event/get_pointer_eventroute incoming messages by object ID into tagged-union events. Works for multi-seat setups. - XKB keymap parsing (
xkb.jai): mmap's the keymap fd fromwl_keyboard.keymap, parses the xkb text format into a 768-entry evdev→keysym lookup table, including named keysyms and xkbcommon-stylesymbols[N]group entries. Layout-independent keysyms replace raw scancodes; physical Alt+F4 has been verified under Hyprland. wl_shmpath with pooled buffers sized to the native screen resolution, so resize is a cheapwl_bufferre-describe (no remap, no syscalls).- Double-buffered painting: two
Buffer_Slotrecords carve the pool at offsets0andframe_max_bytes. Paint picks a non-in-flight slot;wl_buffer.releaseevents free slots. Persistentdirtyflag queues paints when both slots are in flight. - Examples:
hello_globals.jai— prints all compositor globals (~20 lines)hello_screens.jai— prints each output's modes, scale, geometry (~30 lines)hello_window.jai— double-buffered resizable window, keyboard (r/g/b/q keysyms) + pointer (click cycles color), dynamic resize (~220 lines)dump_keymap.jai— diagnostic: prints evdev→keysym mappings from the live compositor's keymap
- 114 tests across 7 test suites (xml, generator, wire, xkb, marshal, unmarshal, compile)
- Tested live against Hyprland compositor on Artix Linux
Phase 5 (complete, Mesa + NVIDIA/hybrid): GPU rendering via OpenGL 3.3 core, end-to-end GL → DMA-BUF → Wayland without any libwayland or libGL linkage.
- Vendored GPU bindings —
modules/EGL/,modules/gbm/,modules/GL/. Same pattern as the Wayland wire code: types + constants + function-pointer variable declarations in one file,init_X()loader in another (dlopen+dlsym). No#foreign, no build-time linkage. We vendor our own minimal GL instead of using Jai's stock GL module because Jai'sglad_core.jaihard-linkslibGLand itsGL.jaiimportsWindow_Typewhich pulls in X11 transitively. - GPU selection —
modules/gpu/discovers DRM render nodes, reads vendor IDs, and supportsJAI_WAYLAND_RENDER_NODE=/dev/dri/renderD129orJAI_WAYLAND_GPU_VENDOR=nvidia|intel|amdoverrides. The default policy preserves the first usable render node. - EGL setup —
EGL_PLATFORM_GBM_KHRon a non-privileged DRM render node. GL 3.3 core context, surfaceless (render to FBOs, never bind a surface). - Primary DMA-BUF path — GBM BO-backed render targets: allocate
gbm_bo, import it as anEGLImage, bind it to a GL texture withglEGLImageTargetTexture2DOES, render through an FBO, then export the BO fd/stride/offset/modifier to Wayland. Mesa usesEGL_NATIVE_PIXMAP_KHR; NVIDIA falls back toEGL_LINUX_DMA_BUF_EXTimport because proprietary NVIDIA rejects native pixmap import. - Fallback DMA-BUF path — the older Mesa texture-export route remains available:
eglCreateImageKHR(EGL_GL_TEXTURE_2D_KHR, tex)plusEGL_MESA_image_dma_buf_export. - wl_buffer from DMA-BUF —
modules/wayland/dmabuf.jaidiscovers compositor formats viazwp_linux_dmabuf_v1and, when available,zwp_linux_dmabuf_feedback_v1per-surface tranches.hello_glfilters feedback through GBM device capability before creatingwl_bufferobjects withzwp_linux_buffer_params_v1.add/create_immed. - Frame pacing —
wl_surface.framecallbacks gate the next render to compositor vsync.wl_callback.doneclears theframe_requestedflag and lets the render defer re-fire. - Double-buffered and resize-safe — two
Gl_Slotrecords (each holdingtex+fbo+EGLImage+ optionalgbm_bo+ DMA-BUF fd +wl_buffer) rotate onwl_buffer.release. Resizes retire in-flight slots and destroy them only after their release event arrives. - Input — the Phase 4 seat/keyboard/pointer/xkb helpers plug directly into the GL render loop unchanged.
ldd build/hello_gl—libc.so.6only. Zero hard-linkage to libEGL, libgbm, libGL, libwayland, libX11, libxcb.- Vulkan binding baseline —
modules/Vulkan/vendors Jai's stock Vulkan module, with generated commands converted from#foreign libvulkandeclarations into runtime-loadedPFN_vk*function-pointer variables.init_vulkan()loads the platform loader withdlopen/LoadLibrary, then populates global, instance, and device commands throughvkGetInstanceProcAddr/vkGetDeviceProcAddr. Convenience enumeration wrappers are retained with_Arraysuffixes to avoid colliding with raw command pointers. - Vulkan DMA-BUF baseline —
headless_vulkan_dmabuf.jaicreates a Vulkan image usingVK_EXT_image_drm_format_modifier, allocates exportable external memory, binds it, and exports the image memory as a DMA-BUF fd viavkGetMemoryFdKHR. This is the project-compatible Vulkan presentation direction.VK_KHR_wayland_surfaceexpectslibwayland-clientwl_display*/wl_surface*proxy objects, not jai-wayland wire IDs, so direct WSI swapchains are intentionally not the first path. - Vulkan presentation smoke —
hello_vulkan_dmabuf.jaicreates a real Wayland window, selects a compositor-compatible DRM modifier from dmabuf surface feedback, renders a rotating RGB triangle through a Vulkan graphics pipeline, releases images toVK_QUEUE_FAMILY_EXTERNAL, exports their fds, createswl_bufferobjects, and presents them through double-buffered, frame-paced, resize-safe slots.first.jaicompiles its GLSL shaders withglslc. SetJAI_WAYLAND_VULKAN_FRAMES=Nfor bounded live smoke runs. - X11 compatibility binding baseline —
modules/X11/vendors Jai's stockX11/module.jaiwithoutX11/sofd, converts Xlib/GLX#foreigncalls into runtime-loaded function pointers, and exposesinit_x11()/init_glx()loaders. This is separate from the Wayland implementation and backs the vendoredWindow_Creation/Simp/GetRectX11 path;Input/x11.jaimapsMotionNotifyintomouse_delta_x/yso XWayland camera controls work.x11_smoke.jaiandhello_x11_gl.jaiverify Xlib/GLX loading and GL rendering withoutlibX11,libGLX,libGL, orlibxcbunderldd. SetJAI_WAYLAND_X11_GL_FRAMES=Nfor boundedhello_x11_glsmoke runs. - Examples added:
headless_gl.jai— EGL/GL/gbm smoke test (BO-backed FBO readback + DMA-BUF export, no Wayland)headless_vulkan.jai— Vulkan loader smoke test (no Wayland, no link-time libvulkan)headless_vulkan_dmabuf.jai— Vulkan external-memory / DMA-BUF export smoke testx11_smoke.jai— Xlib/GLX runtime-loader smoke test (no Wayland, no link-time X11/GLX)hello_x11_gl.jai— rotating GL triangle in an X11/GLX window through runtime-loaded Xlib/GLX/GLhello_dmabuf.jai— prints the compositor's advertised format/modifier table plus dmabuf feedback snapshotshello_gl.jai— rotating RGB triangle in a resizable Wayland window with keyboard + pointer input (the Phase 5 + NVIDIA shippable milestone)hello_vulkan_dmabuf.jai— rotating Vulkan triangle → DMA-BUF → Wayland presentation smoke test
- Tested live against Hyprland + Mesa radeonsi on AMD and on a hybrid Intel iGPU + NVIDIA dGPU laptop.
Phase 6 (complete): Vendored upstream window/graphics stack on Wayland — Window_Creation / Simp / Input / GetRect run on the Wayland backend, picking X11 vs Wayland by runtime value, not link-time #if.
modules/Wayland_Support.jai— the GPU-aware support layer above the pure wirewaylandmodule, imported by name from Simp/Input/Window_Creation. The Wayland analogue ofmodules/X11: shared module-scope globals for thewayland_global_windowsregistry, the single shared EGL/GBM/GL context used by all Simp Wayland windows, per-window BO slots/dmabuf choices/frame state, acquired keyboard/pointer/touch/data-device objects, the parsed keymap, plus the SINGLE event pump (wl_pump) that drains the one compositor connection and routes every message — render (frame callback / buffer release / configure / close) and input (decoded into stableWl_Input_Events) — in one pass. Backend selection is aDisplay_Managerenum value branched at the backend op sites, replacing the earliercontext.simp_dispatchfunction-pointer indirection.- Vsync-paced triple-buffered present —
wl_present_and_pacepaces to vsync via the previous frame'swl_surface.framecallback (so a CPU-bound app finds it already fired and never blocks, while a fast app caps to vsync), with a bounded wait (50 ms) so occluded windows do not stall visible siblings. This mirrors the blocking, vsync-locked buffer swap Simp inherits from the platform default on Windows/macOS/Android (SwapBuffers/flushBuffer/eglSwapBuffers) — it is the single, faithful Simp present policy. (A selectablemailbox/immediatepresent-mode experiment was tried and removed; vsync-paced FIFO is what every platform Simp targets gives you by default. Seedocs/plans/2026-05-31-wayland-async-present.md.) - Full input — keyboard (modifier-aware xkb keysyms +
TEXT_INPUT, client-synthesized autorepeat replayed at the compositor'swl_keyboard.repeat_inforate since Wayland sends no repeat events, and command-chord suppression soCtrl/Alt/Meta+ key never inserts a literal character — e.g.Ctrl+C/V/Xin a text field), pointer (motion / buttons / wheel / focus), structural touch, compositor-driven resize (Window_Resize_Records), and.QUIT/ Alt+F4 / close-button quit. - Drag-and-drop —
wl_data_devicefile drops: the pump decodes the drag session (server-allocatedwl_data_offerids ride throughunmarshal's*Interfacepath), pipes thetext/uri-listtransfer overSCM_RIGHTSon drop, and emitsEvent.DRAG_AND_DROP_FILES— full parity with X11'senable_drag_and_drop. Verified by dropping a file from PCManFM-Qt onto the GetRect example. - Clipboard copy/paste — text selection over the same
wl_data_device, backing the vendoredClipboardmodule'sos_clipboard_get_text/set_text(so GetRect's text-input Ctrl+C/V works). Paste reads the current selection offer; copy owns the selection via awl_data_sourceand servessendrequests. Verified end-to-end withwl-copy/wl-paste+wtypeagainst thehello_clipboardexample. - Nine upstream-unmodified graphical examples run on Wayland —
invaders(2D game),skeletal-animation(3D depth-tested skinned mesh + GetRect UI), theGetRect/GetRect_LeftHandedimmediate-mode widget showcases,treemap,codex_view, and the upstream Simp examplessimp_example,simp_multiple_windows, andsimp_render_to_texture. Each links zero display-server/GPU libs (libm+ invaders'libasoundonly — verify withldd build/{invaders,anim,getrect_example,treemap,codex_view,simp_multiple_windows}). - Multi-window Simp on Wayland —
simp_multiple_windowsuses the shared Wayland EGL context with per-window BO slots; compositor resize/close events wake the app out of frame pacing so animation, color cycling, resize, and close requests keep flowing under Hyprland tiling. - Upstream runtime assets are staged by the build —
treemapgetsOpenSans-BoldItalic.ttfnext to thebuild/executable;codex_viewgets itsdata/directory plus sample.codexrecordings (codex_view.codex,sokoban.codex) linked intobuild/. - Project Phase 6 smoke examples —
hello_simp.jai(vendored Simp + Input on Wayland: an animated quad, compositor-driven resize,qto quit) andhello_clipboard.jai(clipboard copy/paste through the vendoredClipboardmodule —ccopies,ppastes,qquits).hello_clipboardalso echoes every key press andTEXT_INPUTchar with its modifier + autorepeat flags, which doubles as the keyboard input smoke test for autorepeat and command-chord suppression. Both accept aJAI_WAYLAND_{SIMP,CLIPBOARD}_FRAMES=Ncap for bounded headless runs.
Known gaps (next phases):
- Clipboard bitmaps —
os_clipboard_set_bitmapis a logged no-op on the Wayland backend; text copy/paste works. - Explicit fence sync — the present path still does a coarse
glFinish()(~0.68 ms/frame) before handing buffers to the compositor;Gl_Slothas placeholder fence fd fields for futureEGL_KHR_fence_sync/wp_linux_drm_syncobj_v1work. (The bigger present cost — a synchronous frame-callback block, ~3.3 ms/frame — is gone as of 2026-05-31: present now throttles on the previous frame callback. Seedocs/plans/2026-05-31-wayland-async-present.md.) - Bucketed GPU slot capacity — done (
docs/plans/2026-06-03-wayland-bucketed-slots.md): each window's logical size is decoupled from its BO/EGLImage/GL/wl_buffer allocation capacity, which grows in 256 px buckets (capped at the output, grow-only) and is reallocated only when the logical size exceeds it; smaller resizes just re-crop the oversized buffer withwp_viewporter, eliminating the per-configure slot-stack churn and making resize noticeably smoother. Validated band-free onhello_simp,getrect_example,skeletal_animation,invaders, andsimp_multiple_windows. (Supersedes an abandoned active-resize-sleep experiment.) - Explicit Vulkan/Wayland sync, AltGr / level-3 keysyms,
wp_relative_pointer_v1, fractional scaling — seeCLAUDE.mdNext Steps. - Tiling-WM floating-widget sizing (curiosity, not a rendering bug). Under a tiling compositor that force-resizes a window away from its requested size (e.g. Hyprland tiling a 1920×1080 request to fill a tile), GetRect's once-baked floating sub-windows render larger on the Wayland backend than on XWayland / Windows / macOS — the per-frame UI (title, background) is pixel-identical. Cause is first-frame ordering: xdg-shell makes our Wayland
create_windowlearn the forced size synchronously (wait-for-configure-before-map), so the app bakes its sub-windows against it on frame 1, whereas X11/Win/macOS deliver the forced size as an asynchronous resize processed after the first bake. It vanishes entirely when the window opens at its requested size (any floating/stacking WM — verified). A future opt-inJAI_WAYLAND_ENABLE_TM_QUIRKSwould defer Wayland's first resize event by one frame to match the other platforms; default off, since most users run floating/stacking WMs where it can't arise. SeeCLAUDE.mdNext Steps for the full mechanism. - Ergonomic "raylib-light" layer on top of the raw primitives is the eventual target; the current
hello_gl.jaiis the proving ground, not the user-facing API.
Requires the Jai compiler (beta 0.2.029 — see the note at the top of this file) at ~/jai/jai/. The Vulkan triangle
example also expects glslc in PATH; first.jai invokes it to compile GLSL
into SPIR-V under build/shaders/.
./build.sh # Build → build/main
./build.sh - test # 22 XML/protocol tests
./build.sh - gen_test # 35 generator tests
./build.sh - wire_test # 22 wire protocol tests
./build.sh - xkb_test # 3 XKB keymap parser tests
./build.sh - marshal_test # 9 marshal macro tests
./build.sh - unmarshal_test # 12 unmarshal macro tests
./build.sh - compile_test # 11 compilation smoke tests
./build.sh - generate # Regenerate modules/wayland/ from protocol XML
./build.sh - hello_globals # Build and run: print compositor globals
./build.sh - hello_screens # Build and run: print output discovery
./build.sh - hello_window # Build and run: resizable double-buffered shm window
./build.sh - dump_keymap # Build and run: xkb keymap diagnostic
./build.sh - headless_gl # Build and run: EGL/GL/gbm + DMA-BUF export smoke test
./build.sh - headless_vulkan # Build and run: runtime-loaded Vulkan loader smoke test
./build.sh - headless_vulkan_dmabuf # Build and run: Vulkan image external-memory / DMA-BUF export smoke test
./build.sh - x11_smoke # Build and run: runtime-loaded Xlib/GLX smoke test
./build.sh - hello_x11_gl # Build and run: X11/GLX rotating triangle
./build.sh - hello_dmabuf # Build and run: zwp_linux_dmabuf_v1 format discovery
./build.sh - hello_gl # Build and run: GPU-rendered rotating triangle (GL → DMA-BUF → Wayland)
./build.sh - hello_vulkan_dmabuf # Build and run: Vulkan triangle → DMA-BUF → Wayland window
./build.sh - hello_simp # Build and run: vendored Simp + Input smoke (animated quad, resize, q quits)
./build.sh - hello_clipboard # Build and run: clipboard copy/paste + input echo (c copies, p pastes, q quits)
./build.sh - invaders # Build and run: upstream invaders (2D game) on the Wayland backend
./build.sh - skeletal_animation # Build and run: upstream skeletal-animation (3D mesh + GetRect UI) on Wayland
./build.sh - getrect_example # Build and run: upstream GetRect immediate-mode UI showcase (RIGHT_HANDED)
./build.sh - getrect_lh_example # Build and run: upstream GetRect_LeftHanded UI showcase (LEFT_HANDED)
./build.sh - treemap # Build and run: upstream treemap example; stages OpenSans-BoldItalic.ttf
./build.sh - codex_view # Build and run: upstream codex_view; stages data/ and sample .codex files
./build.sh - simp_example # Build and run: upstream Simp example; stages font + image assets
./build.sh - simp_multiple_windows # Build and run: upstream Simp multiple-windows example; stages font asset
./build.sh - simp_render_to_texture # Build and run: upstream Simp render-to-texture example
./build.sh - compile_only <target> # Compile a target headlessly without running it (gate for GUI examples that would otherwise hang)The build uses Jai's compile-time metaprogramming via first.jai; use the
project wrapper instead of invoking shader compilers or examples by hand. The
invaders, skeletal_animation, getrect_example, getrect_lh_example,
treemap, codex_view, simp_example, simp_multiple_windows, and
simp_render_to_texture targets build and run upstream's unmodified example
sources from the Jai distribution against the vendored modules.
src/
xml.jai — Zero-copy XML pull parser
protocol.jai — Protocol data model + parser
generator.jai — Code generator (naming, enums, events, requests, assembly)
generate_main.jai — Generator entry point (file I/O, deduplication)
main.jai — Validation harness
tests/
xml_test.jai — 22 tests (parser, entities, protocol)
generator_test.jai — 35 tests (naming, enums, events, requests, assembly)
wire_test.jai — 22 tests (primitive read/write, header, string/array, buffers)
xkb_test.jai — 3 tests (compact hex/named keysyms, symbols[N] group form)
marshal_test.jai — 9 tests (fixed args, fd, string, array, constructors)
unmarshal_test.jai — 12 tests (round-trip, tagged union dispatch)
compile_test.jai — 11 tests (imports generated module, verifies types)
examples/
hello_globals.jai — ~20 lines: connect, discover globals, print them
hello_screens.jai — ~30 lines: output discovery (modes, scale, geometry)
hello_window.jai — ~270 lines: double-buffered resizable shm window, keyboard + pointer input, XKB keysym translation
dump_keymap.jai — mmap keymap fd, print evdev→keysym mappings for letters, digits, F-keys, and modifiers
headless_gl.jai — EGL/GL/gbm smoke test + BO-backed DMA-BUF export (no Wayland)
headless_vulkan.jai — Vulkan loader smoke test (no Wayland, no libvulkan link)
headless_vulkan_dmabuf.jai — Vulkan image + external memory + DMA-BUF fd export smoke test
x11_smoke.jai — Xlib/GLX runtime-loader smoke test
hello_x11_gl.jai — rotating GL triangle through X11/GLX runtime-loaded bindings
hello_dmabuf.jai — print compositor format/modifier pairs and dmabuf feedback snapshots
hello_gl.jai — GPU-rendered rotating triangle via GL → DMA-BUF → Wayland, BO-backed, resizable, frame-paced, keyboard + pointer input
hello_vulkan_dmabuf.jai — rotating Vulkan triangle via DRM-modifier DMA-BUF in a Wayland window
hello_simp.jai — ~120 lines: vendored Simp + Input smoke (animated quad, resize, q quits)
hello_clipboard.jai — ~105 lines: clipboard copy/paste via the vendored Clipboard module + keyboard echo (autorepeat + command-chord-suppression smoke test)
shaders/ — GLSL sources compiled by first.jai for Vulkan examples
modules/
wayland/ — Generated Jai bindings (56 protocols, 175 interfaces)
module.jai — Module root (#load chain)
types.jai — Shared types (Fixed, Fd, Interface_Descriptor, Wire_Arg_Type)
wire.jai — Wire primitives (read/write, header, string/array encoding)
connection.jai — Connection / MessageBuilder / ReceiveBuffer; sendmsg/recvmsg with SCM_RIGHTS
marshal.jai — Compile-time marshal macro (#expand + #insert #run)
unmarshal.jai — Compile-time unmarshal macro (event decode + tagged union dispatch)
session.jai — WaylandSession actor, for_expansion event loop, context-based convenience API
registry.jai — discover_globals, find_global, init_display helpers
output.jai — get_screens_info (wl_output discovery)
input.jai — Seat-based input: get_seats_info, get_keyboards_info, get_pointers_info
xkb.jai — XKB keymap parser (evdev keycode → keysym lookup)
shm.jai — memfd_create syscall wrapper
dmabuf.jai — zwp_linux_dmabuf_v1 discovery and dmabuf feedback helpers
wayland/ — Core protocol (wl_display, wl_surface, wl_buffer, etc.)
xdg_shell/ — XDG shell (xdg_toplevel, xdg_surface, etc.)
... — 54 more protocol directories
gpu/ — Render-node selection, GBM BO allocation, EGLImage import helpers
EGL/ — Runtime-dlopen'd EGL 1.5 bindings (core + image/dmabuf extension entry points)
gbm/ — Runtime-dlopen'd libgbm bindings (device + BO allocation/export helpers)
GL/ — Runtime-dlopen'd minimal GL 3.3 core bindings (~40 entry points, loaded via eglGetProcAddress)
Vulkan/ — Vendored Vulkan bindings with runtime-loaded PFN_vk* command pointers and Linux DRM modifier supplement
X11/ — Vendored Xlib/GLX bindings with runtime-loaded function pointers; no sofd in first pass
Wayland_Support.jai — Phase 6 backend layer: shared-globals window registry + shared EGL/GBM context + single event pump (wl_pump); GL-on-GBM, DMA-BUF present, input decode, drag-and-drop + clipboard
Window_Type.jai — Tagged Window_Type (X11 | Wayland identity) + the drag-and-drop opt-in flag both backends share
Window_Creation/ — Vendored upstream window creation; Linux create_window picks Wayland vs X11 by runtime value
Simp/ — Vendored upstream Simp renderer; backend/{x11,wayland}_dispatch.jai select per-op by value
Input/ — Vendored upstream Input; wayland.jai drains Wayland_Support's decoded input events
GetRect/ — Vendored upstream immediate-mode UI toolkit (RIGHT_HANDED)
GetRect_LeftHanded/ — Vendored upstream immediate-mode UI toolkit (LEFT_HANDED)
Clipboard/ — Vendored upstream Clipboard; Linux os_clipboard_* routes to Wayland_Support under running_wayland()
vendor/
wayland-protocols/ — Vendored protocol XML (core, stable, staging, unstable) — regenerated into modules/wayland/
reference/ — zig-wayland and wayland-rs sources for reference
docs/plans/ — Design + implementation plan docs (one per phase/feature)
first.jai — Build metaprogram
59 XML protocol definitions from /usr/share/wayland/ and /usr/share/wayland-protocols/:
- Core:
wayland.xml(23 interfaces) - Stable: xdg-shell, viewporter, tablet, presentation-time, linux-dmabuf
- Staging: 31 protocols (cursor-shape, fractional-scale, xdg-dialog, etc.)
- Unstable: 20 protocols (xdg-decoration, pointer-constraints, relative-pointer, etc.)
The original code authored for jai-wayland is licensed under the
MIT License — the protocol XML parser and code generator (src/),
the hand-written wire/session/discovery layer and the generated bindings
(modules/wayland/), the runtime GPU loaders (modules/gpu, modules/EGL,
modules/gbm), the Wayland_Support backend layer, and the examples/ and
tests/.
The repository also bundles third-party code that keeps its own license; the MIT grant does not extend to it:
vendor/wayland-protocols/— upstream Wayland protocol XML, each file under its own copyright/permission notice (MIT/HPND-style). The generated bindings reproduce each protocol's notice in their file headers.modules/{Simp, GetRect, GetRect_LeftHanded, Input, Window_Creation, Clipboard, X11, Vulkan, Window_Type, GL}— vendored from, or derived from, the Jai compiler distribution; © Thekla, Inc. (and their respective upstreams), under that distribution's terms. They are included only so the upstream graphical examples build, and are not relicensed here.