mirror of
https://github.com/rust-windowing/winit.git
synced 2026-06-27 23:23:14 -04:00
Web: improve custom cursor handling and add animated cursors (#3384)
This commit is contained in:
78
src/platform_impl/web/async/notifier.rs
Normal file
78
src/platform_impl/web/async/notifier.rs
Normal file
@@ -0,0 +1,78 @@
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
use std::task::Waker;
|
||||
|
||||
use super::{ConcurrentQueue, PushError};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Notifier<T: Clone>(Arc<Inner<T>>);
|
||||
|
||||
impl<T: Clone> Notifier<T> {
|
||||
pub fn new() -> Self {
|
||||
Self(Arc::new(Inner {
|
||||
queue: ConcurrentQueue::unbounded(),
|
||||
value: OnceLock::new(),
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn notify(self, value: T) {
|
||||
if self.0.value.set(value).is_err() {
|
||||
unreachable!("value set before")
|
||||
}
|
||||
|
||||
self.0.queue.close();
|
||||
|
||||
while let Ok(waker) = self.0.queue.pop() {
|
||||
waker.wake()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn notified(&self) -> Notified<T> {
|
||||
Notified(Some(Arc::clone(&self.0)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Notified<T: Clone>(Option<Arc<Inner<T>>>);
|
||||
|
||||
impl<T: Clone> Future for Notified<T> {
|
||||
type Output = T;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.0.take().expect("`Receiver` polled after completion");
|
||||
|
||||
if this.value.get().is_none() {
|
||||
match this.queue.push(cx.waker().clone()) {
|
||||
Ok(()) => {
|
||||
if this.value.get().is_none() {
|
||||
self.0 = Some(this);
|
||||
return Poll::Pending;
|
||||
}
|
||||
}
|
||||
Err(PushError::Closed(_)) => (),
|
||||
Err(PushError::Full(_)) => {
|
||||
unreachable!("found full queue despite using unbounded queue")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (Ok(Some(value)) | Err(Some(value))) = Arc::try_unwrap(this)
|
||||
.map(|mut inner| inner.value.take())
|
||||
.map_err(|this| this.value.get().cloned())
|
||||
else {
|
||||
unreachable!("found no value despite being ready")
|
||||
};
|
||||
|
||||
Poll::Ready(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Inner<T> {
|
||||
queue: ConcurrentQueue<Waker>,
|
||||
value: OnceLock<T>,
|
||||
}
|
||||
Reference in New Issue
Block a user