use smithay::{
backend::renderer::{Color32F, Frame},
input::pointer::CursorImageSurfaceData,
reexports::wayland_server::protocol::wl_surface::WlSurface,
utils::{Physical, Rectangle},
wayland::compositor::with_states,
};
use super::cursor_theme::SoftwareCursorSprite;
use super::draw_primitives::draw_rect;
pub(crate) fn cursor_surface_hotspot(surface: &WlSurface) -> (i32, i32) {
with_states(surface, |states| {
states
.data_map
.get::<CursorImageSurfaceData>()
.and_then(|attrs| {
attrs
.lock()
.ok()
.map(|attr| (attr.hotspot.x, attr.hotspot.y))
})
.unwrap_or((0, 0))
})
}
pub(crate) fn draw_cursor_sprite<F: Frame>(
frame: &mut F,
damage: Rectangle<i32, Physical>,
cursor_screen: (f32, f32),
sprite: &SoftwareCursorSprite,
) -> Result<(), F::Error> {
let (sx, sy) = cursor_screen;
let x0 = sx.round() as i32 - sprite.hotspot_x;
let y0 = sy.round() as i32 - sprite.hotspot_y;
let w = sprite.width;
let h = sprite.height;
for y in 0..h {
let mut x = 0usize;
while x < w {
let base = (y * w + x) * 4;
let a = sprite.pixels_bgra[base + 3];
if a == 0 {
x += 1;
continue;
}
let b = sprite.pixels_bgra[base];
let g = sprite.pixels_bgra[base + 1];
let r = sprite.pixels_bgra[base + 2];
let mut run_end = x + 1;
while run_end < w {
let i = (y * w + run_end) * 4;
if sprite.pixels_bgra[i] != b
|| sprite.pixels_bgra[i + 1] != g
|| sprite.pixels_bgra[i + 2] != r
|| sprite.pixels_bgra[i + 3] != a
{
break;
}
run_end += 1;
}
draw_rect(
frame,
x0 + x as i32,
y0 + y as i32,
(run_end - x) as i32,
1,
Color32F::new(
r as f32 / 255.0,
g as f32 / 255.0,
b as f32 / 255.0,
a as f32 / 255.0,
),
damage,
)?;
x = run_end;
}
}
Ok(())
}