6 Protocol Bindings
dxtr edited this page 2026-10-17 12:44:14 +02:00

Protocol Bindings

cl-wl ships bindings for eleven protocols. Each is an ASDF system and a package, generated from an XML file vendored in protocols/.

System Package Source Depends on
cl-wl cl-wl/wayland wayland.xml, Wayland 1.26.0 —
cl-wl/xdg-shell cl-wl/xdg-shell stable/xdg-shell, wayland-protocols 1.49 core
cl-wl/xdg-decoration cl-wl/xdg-decoration unstable/xdg-decoration v1, wayland-protocols 1.49 core, xdg-shell
cl-wl/viewporter cl-wl/viewporter stable/viewporter, wayland-protocols 1.49 core
cl-wl/fractional-scale cl-wl/fractional-scale staging/fractional-scale v1, wayland-protocols 1.49 core
cl-wl/tablet cl-wl/tablet stable/tablet v2, wayland-protocols 1.49 core
cl-wl/cursor-shape cl-wl/cursor-shape staging/cursor-shape v1, wayland-protocols 1.49 core, tablet
cl-wl/text-input cl-wl/text-input unstable/text-input v3, wayland-protocols 1.49 core
cl-wl/pointer-constraints cl-wl/pointer-constraints unstable/pointer-constraints v1, wayland-protocols 1.49 core
cl-wl/relative-pointer cl-wl/relative-pointer unstable/relative-pointer v1, wayland-protocols 1.49 core
cl-wl/xdg-dialog cl-wl/xdg-dialog staging/xdg-dialog v1, wayland-protocols 1.49 core, xdg-shell

cl-wl/cursor, for cursor themes, is not a protocol but a binding of libwayland-cursor; see Cursors.

The version in the table below is the newest that the bindings support, which bind caps at. (wl:supported-version class) returns it.

Core protocol: cl-wl/wayland

Class Version What it is
wl-display 1 The connection itself. cl-wl:display objects are instances of it.
wl-registry 1 Global announcements. bind manages one for you.
wl-callback 1 A one-shot :done notification (wl-display-sync, wl-surface-frame), destroyed by its :done.
wl-compositor 7 Creates surfaces and regions.
wl-shm 3 Shared-memory buffers, made from a cl-wl:shared-memory.
wl-shm-pool 3 A shared-memory pool that buffers are cut from.
wl-buffer 1 Pixel contents for a surface.
wl-data-device-manager 4 Clipboard and drag and drop.
wl-data-device, wl-data-source, wl-data-offer 4 Its objects.
wl-shell, wl-shell-surface 1 The deprecated shell, superseded by xdg-shell.
wl-surface 7 A rectangle the compositor shows.
wl-region 7 A set of rectangles (input and opaque regions).
wl-seat 11 A group of input devices.
wl-pointer 11 Mouse and touchpad.
wl-keyboard 11 Keyboard.
wl-touch 11 Touch screen.
wl-output 4 A monitor.
wl-subcompositor, wl-subsurface 1 Surfaces positioned relative to a parent.
wl-fixes 2 Fixes to the core protocol, such as destroying a registry.

Enums include wl-shm-format (:argb8888, :xrgb8888, …), wl-seat-capability (bitfield), wl-pointer-button-state, wl-pointer-axis, wl-keyboard-key-state, wl-keyboard-keymap-format, wl-output-transform, wl-output-subpixel, wl-output-mode (bitfield), and an -error enum for each interface that raises errors, such as wl-surface-error.

xdg-shell: cl-wl/xdg-shell

Class Version What it is
xdg-wm-base 7 The global. It answers :ping and makes xdg-surfaces.
xdg-surface 7 Gives a wl-surface a desktop role and carries the configure handshake.
xdg-toplevel 7 A window: title, app id, size, maximize, fullscreen, close.
xdg-popup 7 A menu or tooltip.
xdg-positioner 7 Where a popup goes.

xdg_toplevel.configure's states arrive as a list of xdg-toplevel-state keywords: :maximized, :fullscreen, :resizing, :activated, :tiled-left, :tiled-right, :tiled-top, :tiled-bottom, :suspended, :constrained-left, :constrained-right, :constrained-top and :constrained-bottom. States newer than the bindings arrive as integers.

xdg-decoration: cl-wl/xdg-decoration

Class Version What it is
zxdg-decoration-manager-v1 2 The global.
zxdg-toplevel-decoration-v1 2 Negotiates whether the client or the compositor draws a toplevel's frame.

viewporter: cl-wl/viewporter

Class Version What it is
wp-viewporter 1 The global.
wp-viewport 1 Crops and scales a surface's buffer to a destination size.

fractional-scale: cl-wl/fractional-scale

Class Version What it is
wp-fractional-scale-manager-v1 1 The global.
wp-fractional-scale-v1 1 Sends :preferred-scale for a surface, in 120ths: 180 means 1.5.

Fractional scaling uses viewporter. You draw a buffer at the scaled size and set the viewport's destination to the surface's logical size. See Recipes.

tablet-v2: cl-wl/tablet

Class Version What it is
zwp-tablet-manager-v2 2 The global. zwp-tablet-manager-v2-get-tablet-seat gives a seat's tablets.
zwp-tablet-seat-v2 2 Announces the seat's tablets, tools and pads: :tablet-added, :tool-added, :pad-added.
zwp-tablet-v2 2 A tablet: its :name, :id, :path and :bustype, then :done; :removed when unplugged.
zwp-tablet-tool-v2 2 A pen, eraser, airbrush or other tool: :proximity-in, :down, :motion, :pressure, :distance, :tilt and more, grouped by :frame.
zwp-tablet-pad-v2 2 A pad of buttons, rings, strips and dials beside the tablet: :button, :enter, :leave.
zwp-tablet-pad-group-v2 2 A set of the pad's buttons, rings, strips and dials that switch modes together.
zwp-tablet-pad-ring-v2, zwp-tablet-pad-strip-v2, zwp-tablet-pad-dial-v2 2 A pad's rings, strips and dials: :angle, :position or :delta, grouped by :frame.

Pressure, distance and tilt arrive as the protocol sends them: pressure and distance from 0 to 65535, tilt in degrees.

cursor-shape: cl-wl/cursor-shape

Class Version What it is
wp-cursor-shape-manager-v1 2 The global. -get-pointer gives the device for a wl-pointer, -get-tablet-tool-v2 for a tablet tool.
wp-cursor-shape-device-v1 2 wp-cursor-shape-device-v1-set-shape sets the cursor by name.

The compositor draws the cursor, in the user's theme and at the right scale, from a wp-cursor-shape-device-v1-shape keyword: :default, :text, :pointer, :wait, :progress, :crosshair, :grab, :grabbing, :ew-resize, :ns-resize, :nwse-resize, :nesw-resize, :move, :not-allowed, :all-scroll, :zoom-in, :zoom-out and the rest of the CSS cursor names. Set it after each wl_pointer :enter, with the enter's serial:

(let ((device (wp-cursor-shape-manager-v1-get-pointer manager pointer)))
  (wp-cursor-shape-device-v1-set-shape device serial :text))

The bindings refer to tablet tools, so cl-wl/cursor-shape loads cl-wl/tablet. Where a compositor lacks the global, set cursor images yourself from a cursor theme: see Cursors.

text-input-v3: cl-wl/text-input

Class Version What it is
zwp-text-input-manager-v3 2 The global. zwp-text-input-manager-v3-get-text-input gives a seat's text input.
zwp-text-input-v3 2 Text input through an input method, such as one for Chinese or Japanese.

The client enables the text input while a text field has focus, tells it where the caret is, -set-cursor-rectangle, and what is around it, -set-surrounding-text, and sends them with -commit; from version 2 they take effect at the surface's next wl-surface-commit, so the input method's popup moves in the same frame as the text. The input method sends what it composes: :preedit-string, the text being composed, to show at the caret; :commit-string, the text chosen, to insert; and :delete-surrounding-text. Each batch ends with :done, at which the client applies them in the order the protocol gives: remove the old preedit text, delete the surrounding text asked for, insert the committed text, then show the new preedit text. Version 2 adds :action, :language and :preedit-hint, and the requests to show and hide the input panel.

pointer-constraints: cl-wl/pointer-constraints

Class Version What it is
zwp-pointer-constraints-v1 1 The global. -lock-pointer and -confine-pointer constrain a pointer over a surface.
zwp-locked-pointer-v1 1 The pointer stays where it is: :locked and :unlocked.
zwp-confined-pointer-v1 1 The pointer stays inside the surface, or a region of it: :confined and :unconfined.

The lifetime argument is a zwp-pointer-constraints-v1-lifetime: :oneshot, which ends for good once the constraint is lost, or :persistent, which comes back whenever the surface has the pointer again. A locked pointer sends no motion; read the motion from cl-wl/relative-pointer meanwhile, as games and drawing programs do.

relative-pointer: cl-wl/relative-pointer

Class Version What it is
zwp-relative-pointer-manager-v1 1 The global. -get-relative-pointer gives the relative pointer of a wl-pointer.
zwp-relative-pointer-v1 1 :relative-motion: the pointer's motion as it is.

:relative-motion passes a timestamp in microseconds, as utime-hi and utime-lo, and the motion dx, dy with acceleration and dx-unaccel, dy-unaccel without, as floats. It goes on while the pointer is locked.

xdg-dialog: cl-wl/xdg-dialog

Class Version What it is
xdg-wm-dialog-v1 1 The global. -get-xdg-dialog makes a toplevel a dialog.
xdg-dialog-v1 1 -set-modal and -unset-modal hint whether the dialog is modal.

A dialog is an xdg-toplevel given its parent with xdg-toplevel-set-parent; the protocol only hints how the compositor shows it. A modal one is a hint too: the client keeps the parent's input from the user itself, as the protocol asks.

Reading a binding's documentation

Every generated definition carries the protocol's own description. The generator adds what Lisp needs: the events and their argument types on the class, the arguments on the function, and the entries on the enum type.

(documentation 'xdg-toplevel 'type)            ; the class: events and arguments
(documentation 'xdg-toplevel-set-title 'function)
(documentation 'wl-seat-capability 'type)      ; the enum: entries and values
(describe 'wl-surface-attach)

A class's documentation lists its events like this:

Events, each passed to its EVENT-HANDLER with the proxy and
the arguments shown:
  (:configure WIDTH HEIGHT STATES) -- suggest a surface change
    …
  (:close) -- surface wants to be closed
  (:configure-bounds WIDTH HEIGHT) -- recommended window geometry bounds (since version 4)
  (:wm-capabilities CAPABILITIES) -- compositor capabilities (since version 5)

(since version N) means that the event arrives only on proxies of that version or newer. Requests list the same in their documentation, and calling one on an older proxy signals version-error. An event that ends its object is marked "destroys the proxy after its handler":

  (:done CALLBACK-DATA) -- done event (destroys the proxy after its handler)

The generated sources are also readable. protocols/xdg-shell.lisp consists of define-enum, define-interface and define-request forms, one per protocol element.

Asking a binding from code

The same descriptions are available as message and argument objects, for tools and for code that talks to libwayland directly:

(let ((done (first (wl:interface-events 'wl-callback))))
  (list (wl:message-name done) (wl:message-destructor-p done)))
;; => (:DONE T)
(mapcar #'wl:message-wire-name (wl:interface-requests 'wl-surface))
;; => ("destroy" "attach" "damage" "frame" …)
(mapcar #'wl:argument-type
        (wl:message-arguments (second (wl:interface-requests 'wl-surface))))
;; => (:OBJECT :INT :INT)

See API Reference.

A protocol that is not here

To bind another protocol, such as primary-selection or idle-inhibit, generate it with the scanner. See The Scanner. Every additional protocol lives in cl-wl as a system of its own.