1
0
Fork 0
forked from wry/wry

all: implement hardware cursors

This commit is contained in:
Julian Orth 2022-06-01 21:46:31 +02:00
parent 6cc97ee56e
commit 3b8935cf55
23 changed files with 614 additions and 91 deletions

View file

@ -5,6 +5,7 @@ use {
rect::Rect,
render::{RenderContext, RenderError, Renderer, Texture},
state::State,
time::Time,
tree::OutputNode,
utils::{errorfmt::ErrorFmt, numcell::NumCell, smallmap::SmallMapMut},
},
@ -22,9 +23,9 @@ use {
mem::MaybeUninit,
rc::Rc,
slice, str,
time::Duration,
},
thiserror::Error,
uapi::c,
};
const XCURSOR_MAGIC: u32 = 0x72756358;
@ -38,11 +39,19 @@ const HEADER_SIZE: u32 = 16;
pub trait Cursor {
fn render(&self, renderer: &mut Renderer, x: Fixed, y: Fixed);
fn render_hardware_cursor(&self, renderer: &mut Renderer);
fn extents_at_scale(&self, scale: Fixed) -> Rect;
fn set_output(&self, output: &Rc<OutputNode>) {
let _ = output;
}
fn handle_unset(&self) {}
fn tick(&self) {}
fn needs_tick(&self) -> bool {
false
}
fn time_until_tick(&self) -> Duration {
Duration::new(0, 0)
}
}
pub struct ServerCursors {
@ -183,19 +192,12 @@ impl ServerCursorTemplate {
ServerCursorTemplateVariant::Static(s) => Rc::new(StaticCursor {
image: s.for_size(size),
}),
ServerCursorTemplateVariant::Animated(a) => {
let mut start = c::timespec {
tv_sec: 0,
tv_nsec: 0,
};
uapi::clock_gettime(c::CLOCK_MONOTONIC, &mut start).unwrap();
Rc::new(AnimatedCursor {
start,
next: NumCell::new(a[0].delay_ns),
idx: Cell::new(0),
images: a.iter().map(|c| c.for_size(size)).collect(),
})
}
ServerCursorTemplateVariant::Animated(a) => Rc::new(AnimatedCursor {
start: Time::now_unchecked(),
next: NumCell::new(a[0].delay_ns),
idx: Cell::new(0),
images: a.iter().map(|c| c.for_size(size)).collect(),
}),
}
}
}
@ -237,7 +239,7 @@ impl CursorImage {
sizes: SmallMapMut<(Fixed, u32), Rc<CursorImageScaled>, 2>,
) -> Result<Self, CursorError> {
Ok(Self {
delay_ns: delay_ms * 1_000_000,
delay_ns: delay_ms.max(1) * 1_000_000,
sizes,
})
}
@ -291,10 +293,23 @@ impl Cursor for StaticCursor {
fn render(&self, renderer: &mut Renderer, x: Fixed, y: Fixed) {
render_img(&self.image, renderer, x, y);
}
fn render_hardware_cursor(&self, renderer: &mut Renderer) {
if let Some(img) = self.image.scales.get(&renderer.scale()) {
renderer.render_texture(&img.tex, 0, 0, ARGB8888, None, None, renderer.scale());
}
}
fn extents_at_scale(&self, scale: Fixed) -> Rect {
match self.image.scales.get(&scale) {
None => Rect::new_empty(0, 0),
Some(i) => i.extents,
}
}
}
struct AnimatedCursor {
start: c::timespec,
start: Time,
next: NumCell<u64>,
idx: Cell<usize>,
images: Vec<InstantiatedCursorImage>,
@ -306,15 +321,24 @@ impl Cursor for AnimatedCursor {
render_img(img, renderer, x, y);
}
fn render_hardware_cursor(&self, renderer: &mut Renderer) {
let img = &self.images[self.idx.get()];
if let Some(img) = img.scales.get(&renderer.scale()) {
renderer.render_texture(&img.tex, 0, 0, ARGB8888, None, None, renderer.scale());
}
}
fn extents_at_scale(&self, scale: Fixed) -> Rect {
let img = &self.images[self.idx.get()];
match img.scales.get(&scale) {
None => Rect::new_empty(0, 0),
Some(i) => i.extents,
}
}
fn tick(&self) {
let mut now = c::timespec {
tv_sec: 0,
tv_nsec: 0,
};
uapi::clock_gettime(c::CLOCK_MONOTONIC, &mut now).unwrap();
let dist = (now.tv_sec.wrapping_sub(self.start.tv_sec)) as i64 * 1_000_000_000
+ now.tv_nsec.wrapping_sub(self.start.tv_nsec) as i64;
if (dist as u64) < self.next.get() {
let dist = Time::now_unchecked() - self.start;
if (dist.as_nanos() as u64) < self.next.get() {
return;
}
let idx = (self.idx.get() + 1) % self.images.len();
@ -322,6 +346,17 @@ impl Cursor for AnimatedCursor {
let image = &self.images[idx];
self.next.fetch_add(image.delay_ns);
}
fn needs_tick(&self) -> bool {
true
}
fn time_until_tick(&self) -> Duration {
let dist = Time::now_unchecked() - self.start;
let dist = dist.as_nanos() as u64;
let nanos = self.next.get().saturating_sub(dist);
Duration::from_nanos(nanos)
}
}
struct OpenCursorResult {