cursor.rs

 1use crate::Globals;
 2use util::ResultExt;
 3
 4use wayland_client::protocol::wl_pointer::WlPointer;
 5use wayland_client::protocol::wl_surface::WlSurface;
 6use wayland_client::Connection;
 7use wayland_cursor::{CursorImageBuffer, CursorTheme};
 8
 9pub(crate) struct Cursor {
10    theme: Option<CursorTheme>,
11    surface: WlSurface,
12}
13
14impl Drop for Cursor {
15    fn drop(&mut self) {
16        self.theme.take();
17        self.surface.destroy();
18    }
19}
20
21impl Cursor {
22    pub fn new(connection: &Connection, globals: &Globals, size: u32) -> Self {
23        Self {
24            theme: CursorTheme::load(&connection, globals.shm.clone(), size).log_err(),
25            surface: globals.compositor.create_surface(&globals.qh, ()),
26        }
27    }
28
29    pub fn set_icon(&mut self, wl_pointer: &WlPointer, serial_id: u32, mut cursor_icon_name: &str) {
30        if let Some(theme) = &mut self.theme {
31            let mut buffer: Option<&CursorImageBuffer>;
32
33            if let Some(cursor) = theme.get_cursor(&cursor_icon_name) {
34                buffer = Some(&cursor[0]);
35            } else if let Some(cursor) = theme.get_cursor("default") {
36                buffer = Some(&cursor[0]);
37                cursor_icon_name = "default";
38                log::warn!(
39                    "Linux: Wayland: Unable to get cursor icon: {}. Using default cursor icon",
40                    cursor_icon_name
41                );
42            } else {
43                buffer = None;
44                log::warn!("Linux: Wayland: Unable to get default cursor too!");
45            }
46
47            if let Some(buffer) = &mut buffer {
48                let (width, height) = buffer.dimensions();
49                let (hot_x, hot_y) = buffer.hotspot();
50
51                wl_pointer.set_cursor(serial_id, Some(&self.surface), hot_x as i32, hot_y as i32);
52                self.surface.attach(Some(&buffer), 0, 0);
53                self.surface.damage(0, 0, width as i32, height as i32);
54                self.surface.commit();
55            }
56        } else {
57            log::warn!("Linux: Wayland: Unable to load cursor themes");
58        }
59    }
60}