Cursors
A client sets the pointer's cursor itself, after each wl_pointer
:enter, with the enter's serial: until it does, the cursor over its
surfaces is undefined. There are two ways to give it one.
By name: cursor-shape-v1
Where the compositor offers wp_cursor_shape_manager_v1, the client names
the cursor and the compositor draws it, in the user's theme and at the
surface's scale:
(asdf:load-system :cl-wl/cursor-shape)
(let ((manager (wl:bind display 'cl-wl/cursor-shape:wp-cursor-shape-manager-v1 :errorp nil)))
(when manager
(let ((device (cl-wl/cursor-shape:wp-cursor-shape-manager-v1-get-pointer manager pointer)))
;; In the pointer's :enter handler, with its serial:
(cl-wl/cursor-shape:wp-cursor-shape-device-v1-set-shape device serial :text))))
The names are CSS's, as keywords: :default, :text, :pointer,
:wait, :progress, :crosshair, :grab, :grabbing, :move,
:not-allowed, :ew-resize, :ns-resize, :nwse-resize, :nesw-resize
and the others the type wp-cursor-shape-device-v1-shape lists. Make one
device per pointer and keep it. See Protocol Bindings.
From a cursor theme: cl-wl/cursor
Elsewhere, the client attaches the cursor's image to a surface of its own
and gives that to wl_pointer.set_cursor. cl-wl/cursor loads the images
from the user's cursor theme through libwayland-cursor, into shared memory
of a wl_shm:
(asdf:load-system :cl-wl/cursor)
(cl-wl/cursor:with-cursor-theme (theme shm) ; the user's theme and size
(let* ((cursor (or (cl-wl/cursor:find-cursor theme "text")
(cl-wl/cursor:find-cursor theme "xterm")))
(image (svref (cl-wl/cursor:cursor-images cursor) 0))
(surface (wl-compositor-create-surface compositor)))
(wl-surface-attach surface (cl-wl/cursor:cursor-image-buffer image) 0 0)
(wl-surface-commit surface)
(wl-pointer-set-cursor pointer serial surface
(cl-wl/cursor:cursor-image-hotspot-x image)
(cl-wl/cursor:cursor-image-hotspot-y image))
…))
Themes
(cl-wl/cursor:load-cursor-theme shm &key name size)
nameis the theme, by default the user's, from$XCURSOR_THEMEas other toolkits read it (default-cursor-theme-name), or the theme named"default"when that is not set.sizeis the cursor's size in pixels, by default the user's, from$XCURSOR_SIZE(default-cursor-size), or 24.- For a surface of buffer scale 2, load the theme at twice the size, and set the cursor surface's buffer scale to 2.
Themes are searched for where Xcursor searches, or in $XCURSOR_PATH. A
theme that is not installed falls back to the theme named "default",
then to a few cursors built into libwayland-cursor ("default", "text",
"pointer", "wait" and some more), so some cursors are always found.
with-cursor-theme loads a theme around its body and destroys it on exit.
cursor-theme-name and cursor-theme-size describe a theme, and
cursor-theme-live-p says whether it has been destroyed.
Cursors and images
(find-cursor theme name) returns the theme's cursor of that name, or
nil. Themes name their cursors as CSS does, such as "text" and
"ew-resize", and older themes as X did, such as "xterm", "left_ptr"
and "sb_h_double_arrow": look for both. Finding a cursor again allocates
nothing.
A cursor has a cursor-name and cursor-images, a vector of
cursor-images: one for a still cursor, the frames of an animation for
another. Each image has a cursor-image-width and cursor-image-height,
its hotspot, the point that is the pointer's position, at
cursor-image-hotspot-x and cursor-image-hotspot-y pixels from its top
left corner, and a cursor-image-delay in milliseconds.
cursor-image-buffer returns its wl_buffer, in the ARGB8888 format, to
attach to the cursor surface.
Animated cursors
(cursor-frame cursor milliseconds) returns the index in cursor-images
of the frame to show that many milliseconds into the animation, and the
milliseconds until the next frame, or 0 for a cursor that is not animated.
It allocates nothing. Attach the frame's buffer, commit, and ask again when
the time has passed, from a frame callback or a timer of your own.
Lifetimes and threads
- The theme owns the images' buffers. Never destroy them: they live until
the theme is destroyed, and asking for one again returns the same proxy.
They are borrowed proxies: see
borrow-proxyin the API Reference. - Destroy the theme with
destroy-cursor-themebefore disconnecting its display. Destroying it after signalswl-errorand leaves its memory allocated. - After the theme is destroyed,
find-cursor,cursor-frameandcursor-image-buffersignalwl-error, and the image buffers are forgotten. - A theme follows the thread rules of its display.
The raw libwayland-cursor layer is the package cl-wl/cursor-ffi, in the
system of the same name.