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}