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}