libx11-compat is an in-process implementation of the X Window System client library (Xlib) layered on top of SDL2, SDL2_ttf, and pixman.
It lets existing Xlib clients keep their source unchanged while running on platforms where a conventional X server is unavailable or inconvenient:
macOS without XQuartz, Wayland-only sessions, headless CI, Android apps with their own SDL2 integration, and similar environments.
The library is not a re-implementation of the X11 wire protocol and does not replace a real X server. Its goal is to keep legacy Xlib code building and running while it is being migrated to a different toolkit or display stack.
The build is Makefile-based and organized as small mk/ fragments.
The required dependencies are SDL2, SDL2_ttf, and pixman.
make
make checkmake check runs the in-tree C tests, exported-symbol coverage, Motif link and demo checks, replay-driven UI smoke tests, and system-X11 differential checks.
For faster local loops, use make check-unit, make check-smoke, or make check-differential depending on the subsystem being changed.
Verbose diagnostics for unimplemented or fall-back paths are gated behind a build flag:
make CFLAGS_EXTRA=-DDEBUG_LIBX11_COMPATThe output artifact is build/libX11-compat.so.
Clients link against it the same way they would link against the system libX11.so.
examples/ bundles real Xlib clients built against the local libX11-compat.so:
make examples
build/examples/2048The bundle covers a 2048 game, a paint demo, Conway's Game of Life, an analog clock, an interactive Mandelbrot viewer, a single-runner Processing-style showcase, an SDL-backed clipboard TARGETS probe, and the upstream X.Org x11perf benchmark.
See docs/EXAMPLES.md for the API each example exercises.
The screenshot above is from the larger ViolaWWW port described in Larger Workloads Under Investigation.
Two ports beyond the bundled demos now provide high-value integration coverage for libx11-compat.
They are still compatibility workloads rather than daily-use application ports,
but each exercises behavior that small examples do not reach.
-
Motif: upstream Motif and its demo suite build against the compatibility libraries. Menu posting, pointer grabs, focus changes, text rendering, resource lookups, and selected demo workflows are covered by local replay smoke tests. Screenshot-based differential checks compare selected paths against native X11/Motif and continue to flag visible layout or repaint regressions. Some widget paths still expose layout artifacts or map/expose propagation gaps that require further work.
-
ViolaWWW: the 1992-era Motif web browser builds and runs out of the consolidated
build/tree, loads HTTP pages over the network, renders inline XPM images throughlibXpm-compat, and is covered by replay checks for scrolling, resize redraw, and the Help menu. Recent fixes corrected stale glyphs after wheel scrolling, scrollbar dragging, and resize reflow. HTTPS, complex modern HTML, and several interactive flows are known limitations of the application itself rather than the compatibility layer.make violawww # build ViolaWWW (depends on motif) build/violawww/source/src/vw/vw # launch the browser make check-smoke-violawww # replay-driven smoke checks (scroll + Help menu) make check-differential-violawww # screenshot diff vs system libX11 (needs remote host)
The
check-smoke-*targets use deterministic replay files and in-process snapshots, with artifacts written underbuild/ui-smoke/. They do not requirenode11,xdotool, or a native X11 reference run. SetUI_REPLAY_XVFB=--xvfbonly when a local Xvfb display is useful for the host environment.
The value of these targets is not that they replace a real X11/Motif install today, but that they keep legacy Xlib/Motif code building and running on platforms where no X server is available while migration is in progress.
Both ports rely on community input. Concrete reproducers, screenshot diffs, and small fixes posted to GitHub Issues are the most effective way to push these workloads forward. Specific gaps worth opening issues for include widget paths that misrender, Motif demos that crash or differ visibly from the native baseline, and ViolaWWW interactions (navigation, dialogs, image formats) that do not behave as the historical browser did.
The exported public Xlib surface is listed in tests/api-symbols.txt and enforced by make symbol-coverage.
It covers window, drawable, GC, pixmap, image, event, input, atom, property, color, font, cursor, region, X Resource Manager, and selected Xt/Motif-adjacent compatibility paths for the cases that real Xlib clients exercise.
Selection, property, and resource-manager support is partial;
MIT-SHM is a thin wrapper over the regular image path;
GLX, Xcms, and input methods are intentionally stubbed.
See docs/COVERAGE.md for the per-subsystem status table, surface notes (window manager hints, raster ops, mouse wheel mapping), and compatibility limits.
Most Xlib sources need no edits (porting is a build-system and runtime-environment exercise). The general shape:
- Link the application against
build/libX11-compat.soplus SDL2, SDL2_ttf, and pixman, replacing the system-lX11. - Keep the existing Xlib source unchanged.
- Drive the event loop with
XPending/XNextEventandConnectionNumber+select(); the library pumps SDL internally. - Use
WM_DELETE_WINDOWviaXSetWMProtocolsso the SDL close button produces a clean shutdown. - Run with
SDL_VIDEODRIVER=dummyfor headless CI.
See docs/PORTING.md for the full guide,
including code snippets keyed to the bundled examples and a checklist of cases where the library is a stepping stone rather than a destination (GLX, real XIM, ICC color management, cross-process selection).
Reports of incorrect Xlib semantics, missing entry points that block real applications, and patches that tighten coverage against the manifest in tests/api-symbols.txt are particularly useful.
libX11-compat is available under a permissive MIT-style license.
Use of this source code is governed by an MIT license that can be found in the LICENSE file.
