wayflan

2022-11-07

From-scratch Wayland client implementation

Upstream URL

git.sr.ht/~shunter/wayflan/

Author

Samuel Hunter

License

BSD 3-Clause
README

Wayflan

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 CLOS and CLCS.

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.

Features

  • 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 communication library for Wayland clients, but intends to be a full-duplex library for both Clients and Compositors. The Wayflan project tracker lists all tickets to improve Wayflan, and other Common Lisp systems related to the Linux desktop.

Documentation

Quickstart

This is a brief version of the Hello World example.

This snippet connects to a Wayland compositor 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 compositor 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

Waycalc

Screenshot of Waycalc

Wayruler

Screenshot of Wayruler

Dependencies

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.

Dependencies (12)

  • alexandria
  • babel
  • cffi
  • cl-cairo2
  • cl-colors
  • closer-mop
  • cl-pango
  • cl-xkb
  • input-event-codes
  • parachute
  • plump
  • posix-shm

Dependents (0)

    • GitHub
    • Quicklisp