25 releases

new 0.30.0-alpha3 Jan 23, 2022
0.29.4 Jan 6, 2022
0.29.1 Oct 17, 2021
0.29.0 Jul 24, 2021
0.24.0 Sep 14, 2019

#207 in GUI

Download history 15059/week @ 2021-10-07 15068/week @ 2021-10-14 15104/week @ 2021-10-21 16545/week @ 2021-10-28 16432/week @ 2021-11-04 16688/week @ 2021-11-11 17011/week @ 2021-11-18 17879/week @ 2021-11-25 18551/week @ 2021-12-02 16485/week @ 2021-12-09 15003/week @ 2021-12-16 13693/week @ 2021-12-23 17756/week @ 2021-12-30 19546/week @ 2022-01-06 19139/week @ 2022-01-13 17741/week @ 2022-01-20

76,295 downloads per month
Used in 53 crates (2 directly)

MIT license

918 lines

crates.io docs.rs Continuous Integration codecov


Loading of XCursor images for Wayland client apps. This crate provides helpers to load the system provided cursor images and load them into WlBuffers as well as obtain the necessary metadata to properly display animated cursors.


Wayland cursor utilities

This crate aims to re-implement the functionality of the libwayland-cursor library in Rust.

It allows you to load cursors from the system and display them correctly.

First of all, you need to create a [CursorTheme], which represents the full cursor theme.

From this theme, using the get_cursor method, you can load a specific [Cursor], which can contain several images if the cursor is animated. It also provides you with the means of querying which frame of the animation should be displayed at what time, as well as handles to the buffers containing these frames, to attach them to a wayland surface.


Several functions of this crate send wayland requests under the hood, requiring you to provide a [ConnectionHandle] to load a cursor theme.

use wayland_cursor::CursorTheme;
# use std::ops::Deref;
# use std::thread::sleep;
# use std::time::{Instant, Duration};
# fn test(connection: &mut wayland_client::Connection, cursor_surface: &wayland_client::protocol::wl_surface::WlSurface, shm: wayland_client::protocol::wl_shm::WlShm) {
// Load the default cursor theme.
let mut cursor_theme = CursorTheme::load(&mut connection.handle(), shm, 32).expect("Could not load cursor theme");
let cursor = cursor_theme.get_cursor(&mut connection.handle(), "wait").expect("Cursor not provided by theme");

let start_time = Instant::now();
loop {
    // Obtain which frame we should show, and for how long.
    let millis = start_time.elapsed().as_millis();
    let fr_info = cursor.frame_and_duration(millis as u32);

    // Here, we obtain the right cursor frame...
    let buffer = &cursor[fr_info.frame_index];
    // and attach it to a wl_surface.
    cursor_surface.attach(&mut connection.handle(), Some(&buffer), 0, 0);
    cursor_surface.commit(&mut connection.handle());

    sleep(Duration::from_millis(fr_info.frame_duration as u64));
# }


~47K SLoC