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        let mut cursor_icon_name = cursor_icon_name.clone();
39        if self.current_icon_name != cursor_icon_name {
40            if let Ok(theme) = &mut self.theme {
41                let mut buffer: Option<&CursorImageBuffer>;
42
43                if let Some(cursor) = theme.get_cursor(&cursor_icon_name) {
44                    buffer = Some(&cursor[0]);
45                } else if let Some(cursor) = theme.get_cursor("default") {
46                    buffer = Some(&cursor[0]);
47                    cursor_icon_name = "default".to_string();
48                    log::warn!(
49                        "Linux: Wayland: Unable to get cursor icon: {}. Using default cursor icon",
50                        cursor_icon_name
51                    );
52                } else {
53                    buffer = None;
54                    log::warn!("Linux: Wayland: Unable to get default cursor too!");
55                }
56
57                if let Some(buffer) = &mut buffer {
58                    let (width, height) = buffer.dimensions();
59                    let (hot_x, hot_y) = buffer.hotspot();
60
61                    wl_pointer.set_cursor(
62                        self.serial_id,
63                        Some(&self.surface),
64                        hot_x as i32,
65                        hot_y as i32,
66                    );
67                    self.surface.attach(Some(&buffer), 0, 0);
68                    self.surface.damage(0, 0, width as i32, height as i32);
69                    self.surface.commit();
70
71                    self.current_icon_name = cursor_icon_name;
72                }
73            } else {
74                log::warn!("Linux: Wayland: Unable to load cursor themes");
75            }
76        }
77    }
78}