cursor.rs

 1use crate::platform::linux::wayland::WaylandClientState;
 2use wayland_backend::client::InvalidId;
 3use wayland_client::protocol::wl_compositor::WlCompositor;
 4use wayland_client::protocol::wl_pointer::WlPointer;
 5use wayland_client::protocol::wl_shm::WlShm;
 6use wayland_client::protocol::wl_surface::WlSurface;
 7use wayland_client::{Connection, QueueHandle};
 8use wayland_cursor::{CursorImageBuffer, CursorTheme};
 9
10pub(crate) struct Cursor {
11    theme: Result<CursorTheme, InvalidId>,
12    current_icon_name: String,
13    surface: WlSurface,
14    serial_id: u32,
15}
16
17impl Cursor {
18    pub fn new(
19        connection: &Connection,
20        compositor: &WlCompositor,
21        qh: &QueueHandle<WaylandClientState>,
22        shm: &WlShm,
23        size: u32,
24    ) -> Self {
25        Self {
26            theme: CursorTheme::load(&connection, shm.clone(), size),
27            current_icon_name: "".to_string(),
28            surface: compositor.create_surface(qh, ()),
29            serial_id: 0,
30        }
31    }
32
33    pub fn set_serial_id(&mut self, serial_id: u32) {
34        self.serial_id = serial_id;
35    }
36
37    pub fn set_icon(&mut self, wl_pointer: &WlPointer, cursor_icon_name: String) {
38        if self.current_icon_name != cursor_icon_name {
39            if self.theme.is_ok() {
40                if let Some(cursor) = self.theme.as_mut().unwrap().get_cursor(&cursor_icon_name) {
41                    let buffer: &CursorImageBuffer = &cursor[0];
42                    let (width, height) = buffer.dimensions();
43                    let (hot_x, hot_y) = buffer.hotspot();
44
45                    wl_pointer.set_cursor(
46                        self.serial_id,
47                        Some(&self.surface),
48                        hot_x as i32,
49                        hot_y as i32,
50                    );
51                    self.surface.attach(Some(&buffer), 0, 0);
52                    self.surface.damage(0, 0, width as i32, height as i32);
53                    self.surface.commit();
54
55                    self.current_icon_name = cursor_icon_name;
56                } else {
57                    log::warn!(
58                        "Linux: Wayland: Unable to get cursor icon: {}",
59                        cursor_icon_name
60                    );
61                }
62            } else {
63                log::warn!("Linux: Wayland: Unable to load cursor themes");
64            }
65        }
66    }
67}