cursor: refactor CustomCursor to be dyn

cursor: refactor `CustomCursor` to be `dyn`

Same as for `MonitorHandle`, the source was changed to support
all kinds of sources.
This commit is contained in:
Kirill Chibisov 2025-03-13 17:18:37 +03:00 committed by GitHub
parent a0464ae83b
commit ae28eea406
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 329 additions and 333 deletions

View file

@ -24,50 +24,17 @@ use super::backend::Style;
use super::main_thread::{MainThreadMarker, MainThreadSafe};
use super::r#async::{AbortHandle, Abortable, DropAbortHandle, Notified, Notifier};
use super::ActiveEventLoop;
use crate::cursor::{BadImage, Cursor, CursorImage, CustomCursor as RootCustomCursor};
use crate::cursor::{
Cursor, CursorAnimation, CursorImage, CustomCursorProvider, CustomCursorSource,
};
use crate::platform::web::CustomCursorError;
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub(crate) enum CustomCursorSource {
Image(CursorImage),
Url { url: String, hotspot_x: u16, hotspot_y: u16 },
Animation { duration: Duration, cursors: Vec<RootCustomCursor> },
}
impl CustomCursorSource {
pub fn from_rgba(
rgba: Vec<u8>,
width: u16,
height: u16,
hotspot_x: u16,
hotspot_y: u16,
) -> Result<CustomCursorSource, BadImage> {
Ok(CustomCursorSource::Image(CursorImage::from_rgba(
rgba, width, height, hotspot_x, hotspot_y,
)?))
}
}
#[derive(Clone, Debug)]
pub struct CustomCursor {
pub(crate) animation: bool,
state: Arc<MainThreadSafe<RefCell<ImageState>>>,
}
impl Hash for CustomCursor {
fn hash<H: Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.state).hash(state);
}
}
impl PartialEq for CustomCursor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.state, &other.state)
}
}
impl Eq for CustomCursor {}
impl CustomCursor {
pub(crate) fn new(event_loop: &ActiveEventLoop, source: CustomCursorSource) -> Self {
match source {
@ -81,15 +48,13 @@ impl CustomCursor {
from_url(UrlType::Plain(url), hotspot_x, hotspot_y),
false,
),
CustomCursorSource::Animation { duration, cursors } => Self::build_spawn(
event_loop,
from_animation(
event_loop.runner.main_thread(),
duration,
cursors.into_iter().map(|cursor| cursor.inner),
),
true,
),
CustomCursorSource::Animation(CursorAnimation { duration, cursors }) => {
Self::build_spawn(
event_loop,
from_animation(event_loop.runner.main_thread(), duration, cursors.into_iter()),
true,
)
},
}
}
@ -163,6 +128,26 @@ impl CustomCursor {
}
}
impl CustomCursorProvider for CustomCursor {
fn is_animated(&self) -> bool {
self.animation
}
}
impl Hash for CustomCursor {
fn hash<H: Hasher>(&self, state: &mut H) {
Arc::as_ptr(&self.state).hash(state);
}
}
impl PartialEq for CustomCursor {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.state, &other.state)
}
}
impl Eq for CustomCursor {}
#[derive(Debug)]
pub struct CustomCursorFuture {
notified: Notified<Result<(), CustomCursorError>>,
@ -230,13 +215,16 @@ impl CursorHandler {
this.set_style();
},
Cursor::Custom(cursor) => {
let cursor = cursor.inner;
let cursor = match cursor.cast_ref::<CustomCursor>() {
Some(cursor) => cursor,
None => todo!(),
};
if let SelectedCursor::Loading { cursor: old_cursor, .. }
| SelectedCursor::Image(old_cursor)
| SelectedCursor::Animation { cursor: old_cursor, .. } = &this.cursor
{
if *old_cursor == cursor {
if old_cursor == cursor {
return;
}
}
@ -263,7 +251,7 @@ impl CursorHandler {
drop(state);
this.cursor = SelectedCursor::Loading {
cursor,
cursor: cursor.clone(),
previous: mem::take(&mut this.cursor).into(),
_handle: handle,
};
@ -275,7 +263,7 @@ impl CursorHandler {
},
ImageState::Image(_) => {
drop(state);
this.cursor = SelectedCursor::Image(cursor);
this.cursor = SelectedCursor::Image(cursor.clone());
this.set_style();
},
ImageState::Animation(animation) => {
@ -292,7 +280,7 @@ impl CursorHandler {
this.cursor = SelectedCursor::Animation {
animation: AnimationDropper(animation),
cursor,
cursor: cursor.clone(),
};
this.set_style();
},
@ -650,12 +638,13 @@ async fn from_url(
async fn from_animation(
main_thread: MainThreadMarker,
duration: Duration,
cursors: impl ExactSizeIterator<Item = CustomCursor>,
cursors: impl ExactSizeIterator<Item = crate::cursor::CustomCursor>,
) -> Result<Animation, CustomCursorError> {
let keyframes = Array::new();
let mut images = Vec::with_capacity(cursors.len());
for cursor in cursors {
let cursor = cursor.cast_ref::<CustomCursor>().unwrap();
let state = cursor.state.get(main_thread).borrow();
match state.deref() {
@ -680,7 +669,7 @@ async fn from_animation(
keyframes.push(&keyframe);
drop(state);
images.push(cursor);
images.push(cursor.clone());
}
keyframes.push(&keyframes.get(0));