From-scratch Wayland client for Common Lisp
client/scanner.lisp: Remove unused function %hyphenize
Clarify single-threadedness and server/compositor terminology
Expand docstrings, getting started, API reference



You can also use your local clone with git send-email.


builds.sr.ht status Quicklisp status

The library brand image: a crudely drawn plate of flan with a W on the roof

Wayflan is a from-scratch Wayland communication library for Common Lisp. It is not a binding or a wrapper around libwayland, but a re-implementation of the Wayland protocol. This unties Lisp applications from per-proxy manual memory allocation, toplevel-only C callbacks, and enables a closer interface with lisp.

Wayflan makes a good-faith effort to mimic libwayland behavior not defined in the Wayland spec, to keep compatibility between the two libraries.

Wayflan is not a compositor nor a GUI toolkit. Its purpose is to parse Wayland protocol XML documents and exchange Wayland messages between other processes.

Wayflan is an ongoing project. Things may change to make Wayflan the best client for Common Lisp projects, such as iterating on a better API. If you use Wayflan in any projects, let me know! I'd love to give a heads up and help transition projects to any breaking changes I make along the way.


  • Client support
  • All implementation done in Common Lisp from the socket up
  • Enum values are translated into keywords
  • Wayland protocol introspection
  • ASDF component :wayflan-client-impl generates code from XML. ASDF's extensible components make it possible to teach your program new protocols for Wayland without the need of a special build system.

#Road map

Wayflan is currently only a single-threaded communication library for Wayland clients, but intends to be a full-duplex multi-threadable library for both Clients and Compositors. The Wayflan project tracker lists all tickets to improve Wayflan and other systems for the Freedesktop stack.



This is a brief version of the Hello World example.

This snippet connects to a Wayland server to print all global variables the client can bind to:

(require :wayflan-client) ;; or (require :wayflan)
(use-package :wayflan-client)

(defun run ()
  ;; Try to connect to a server socket at $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY.
  ;; If $WAYLAND_DISPLAY describes an absolute path, connect to that directly.
  (with-open-display (display)
    ;; Create a registry to provide a list of all
    ;; globals the client can bind to.
    (let ((registry (wl-display.get-registry display)))
      ;; Push an event-listening closure to a list that is called
      ;; whenever the registry receives an event.
      (push (lambda (event-name &rest event-args)
              ;; The macro EVCASE dispatches based on the event automatically.
              ;; See examples/hello-world.lisp
              (when (eq event-name :global)
                (destructuring-bind (name interface version) event-args
                  ;; Print all globals, their interface names, and latest
                  ;; supported version
                  (format t "#x~8,'0X ~32S v~D~%"
                          name interface version))))
            (wl-proxy-hooks registry))

      ;; Listen until all wl-registry events are processed
      (format t "wl-registry globals:~%")
      (wl-display-roundtrip display))))

Output: (Abridged, YMMV)

wl-registry globals:
#x00000001 "wl_shm"                         v1
#x00000002 "wl_drm"                         v2
#x00000004 "wl_compositor"                  v4
#x00000005 "wl_subcompositor"               v1
#x00000006 "wl_data_device_manager"         v3
#x0000000C "xdg_wm_base"                    v2
#x00000012 "wp_presentation"                v1
#x00000018 "wp_drm_lease_device_v1"         v1
#x0000001D "wp_viewporter"                  v1
#x00000022 "xdg_activation_v1"              v1
#x00000027 "wl_seat"                        v7
#x00000029 "wl_output"                      v4

#More Examples

Moving Checkerboard Demo

Screenshot of checkerboxed-demo

Cairo Demo

Screenshot of cairo-demo

wl-pointer Demo

Screenshot of wl-pointer-demo

wl-touch Demo

Screenshot of wl-touch-demo

wl-keyboard Demo

Screenshot of wl-keyboard-demo


Screenshot of Waycalc


Screenshot of Wayruler


While these systems aren't a hard requirement, the examples make use of them, and I recommend their use in your own applications:

  • posix-shm, to create shared memory objects for use in wl-shm-pools.
  • cl-cairo2, cl-pango, and cl-colors all combine together to provide tooling for drawing to a buffer.
  • cl-xkb and input-event-codes, to process keyboard events and mouse buttons, respectively.

Of these, posix-shm and cl-xkb have been developed in lock-step with Wayflan, so you might need to pull these to your workstation directly.