Zix11 - X11 client implementation

Recently I started to replace parts of my desktop setup with components written in zig using xlib. Later quickly become a chore to works with and I decided to write own x11 client. I knew that libxcb has formalized XML protocol description and I just need to write a generator with Zig output to capture encoder/decoder parts and handwritten connection state harness around it. Here it is zix11: a Zig-native x11 client which could be used for writing simple apps completely independent of libc and conventional x11 stack.

Supported requests: core, render and mit-shm extensions.

My apps were migrated successfully and I’m quite happy with the result. zix11 provides a direct access to x11 requests/replies + generic functions to sugar boring stuff like:

  • Atom handling with AtomEnum.
  • Typed getProperty to ensure passed x11 property type corresponds with result type.
  • Typed setProperty

And safety improvements:

  • getProperty works with consumer provided buffer making zero allocations and respecting buffer size.
  • All integer handles for different entities have own distinct enum type and hard to misuse.
  • Requests are sync and return errors for the call site you could easily handle.

Supported Zig versions

Zig 0.16. It uses std.Io. Project doesn’t use obscure stdparts and I assume could work on master but it’s not tested.

AI / LLM usage disclosure

Initial version was generated with LLM help. Later design and important parts like libxcb schema validator are handwritten.

3 Likes

I’ve been using/developing an X11 library in Zig for a few years now: GitHub - marler8997/zigx · GitHub

I had a big rewrite when zig 0.15 came out to use zig’s new Reader/Writer which was a big improvement.

2 Likes

I know it’s currently not possible with Io, but I need to point it out: if you use std.posix.poll, your code is only compatible with std.Io.Threaded, no other implementation. I see this pattern all over new projects, they are dependant on a particular implementation.

Oh shoot. Hope you use some kind of generator for all these requests.

There is a read path which doesn’t touch poll. So technically it could be used as “clean” std.Io lib.

Been generating them by hand but at some point I might switch to using the xcb xml files.