os-cursors API
The complete public API of os-cursors — every exported item,
with its signature, contract, and platform behavior. For the what-and-why
(interception techniques, quick start), see the README.
Public API at a glance
Section titled “Public API at a glance”| Item | Kind | Signature | Purpose |
|---|---|---|---|
Cursor | enum | 19 unit variants | The named cursors an app can replace |
Cursor::freedesktop_name | method | fn freedesktop_name(self) -> &'static str | The theme-file name for this cursor |
Cursor::all | method | fn all() -> &'static [Cursor] | Every replaceable cursor |
Image | struct | public fields | One cursor frame: pixels + hotspot + nominal size |
best_image | fn | fn best_image(&[Image], target_px: u32) -> Option<&Image> | Pick the frame for a target pixel size |
install | fn | fn install(Cursor, &[Image], points: f32) -> bool | Replace one cursor (macOS / Windows) |
reset | fn | fn reset() | Remove every installed cursor |
use_xcursor_theme | fn | fn use_xcursor_theme(&Path, name: &str, size_px: u32) -> bool | Point the process at a theme (Linux) |
xcursor::parse | fn | fn parse(&[u8]) -> Option<Vec<Image>> | Decode an XCursor file |
xcursor::write | fn | fn write(&[Image]) -> Vec<u8> | Encode an XCursor file |
enum Cursor
Section titled “enum Cursor”pub enum Cursor { Arrow, IBeam, Crosshair, ClosedHand, OpenHand, PointingHand, ResizeLeft, ResizeRight, ResizeLeftRight, ResizeUp, ResizeDown, ResizeUpDown, ResizeUpLeftDownRight, ResizeUpRightDownLeft, IBeamVertical, OperationNotAllowed, DragLink, DragCopy, ContextualMenu,}Copy, Clone, Debug, PartialEq, Eq, Hash.
The named cursors an app can replace — the intersection of what AppKit
vends and what toolkits request. There is no ResizeColumn/ResizeRow:
every platform aliases them onto ResizeLeftRight/ResizeUpDown.
Cursor::freedesktop_name
Section titled “Cursor::freedesktop_name”pub fn freedesktop_name(self) -> &'static strThe freedesktop cursor-file name — the file inside an XCursor theme’s
cursors/ directory — for this cursor: Arrow → "default", IBeam →
"text", ResizeLeftRight → "ew-resize", DragLink → "alias", etc.
Use it to look up pack files by Cursor.
Cursor::all
Section titled “Cursor::all”pub fn all() -> &'static [Cursor]Every replaceable cursor, for iterating a pack install.
struct Image
Section titled “struct Image”pub struct Image { pub size: u32, // nominal size (XCursor TOC subtype) pub width: u32, pub height: u32, pub hotspot: (u32, u32), // pixels, from the top-left pub delay: u32, // animation frame delay in ms; 0 = static pub bgra: Vec<u8>, // premultiplied BGRA, width * height * 4}Clone, Debug, PartialEq, Eq.
One cursor frame. Pixels are premultiplied BGRA — exactly the XCursor
on-disk pixel format (little-endian ARGB), which is also what Windows alpha
cursors take; macOS swaps to RGBA on install. delay is preserved so
animated cursors round-trip through xcursor::write;
install shows the first frame only.
fn best_image
Section titled “fn best_image”pub fn best_image(images: &[Image], target_px: u32) -> Option<&Image>The best single frame for a target pixel size: the smallest nominal size
>= target_px, else the largest available. Among animation siblings of one
size, the first frame wins. None only for an empty slice.
fn install
Section titled “fn install”pub fn install(cursor: Cursor, images: &[Image], points: f32) -> boolReplace cursor with the best-fitting frame from images. Call on the
UI thread. Installing again replaces the previous image; mixing
install calls builds up a pack one cursor at a time.
- macOS — honors
points(the native arrow is ≈17pt; 20pt with 64px frames renders Retina-crisp). Prefers a frame ≥3×pointsfor headroom. All 19 cursors work; the themed cursor applies process-wide, and the system cursor returns outside your windows. - Windows —
pointsis ignored; cursors show at pixel size, so the frame nearestGetSystemMetrics(SM_CXCURSOR)is used. Only the nine cursors with their own standard handle install (see the README table); the aliased rest returnfalse. - Linux — always
false; useuse_xcursor_theme.
Returns false when the cursor can’t be replaced on this platform, the
slice is empty, or an image is malformed (undersized pixel buffer).
fn reset
Section titled “fn reset”pub fn reset()Remove every installed cursor — the native ones return. The interception
hooks stay armed (harmless), so a later install is cheap. Does not undo
use_xcursor_theme’s environment on Linux.
fn use_xcursor_theme
Section titled “fn use_xcursor_theme”pub fn use_xcursor_theme(themes_dir: &Path, name: &str, size_px: u32) -> boolLinux: point this process at an XCursor theme —
themes_dir/name/cursors/ must exist, or false. Sets XCURSOR_PATH
(prepending themes_dir, keeping the inherited search path for
inherits= fallbacks), XCURSOR_THEME, and XCURSOR_SIZE.
libXcursor and libwayland-cursor read these when the display connection
loads cursors, so this must run before any windowing setup and before
other threads exist (environment mutation is process-global) — first
thing in main. Works on X11 and Wayland alike; see the README for the
cursor-shape-v1 caveat.
macOS / Windows: no-op, returns false — use install.
Module xcursor
Section titled “Module xcursor”The XCursor binary format, pure Rust. An XCursor file holds one logical
cursor at several nominal sizes (plus animation frames); a theme is a
directory of them under cursors/, named by
Cursor::freedesktop_name.
xcursor::parse
Section titled “xcursor::parse”pub fn parse(data: &[u8]) -> Option<Vec<Image>>Every image frame in an XCursor file, in TOC order (sizes ascending,
animation frames consecutive). None on anything malformed — bad magic,
truncated chunks, absurd dimensions (> 1024px). Non-image chunks
(comments) are skipped.
xcursor::write
Section titled “xcursor::write”pub fn write(images: &[Image]) -> Vec<u8>Encode frames as an XCursor file. Give them in TOC order — sizes
ascending; parse’s output order round-trips exactly.
Useful for stripping themes to one size or generating packs (e.g. from
rasterized SVGs).