mirror of
https://github.com/rust-windowing/winit.git
synced 2026-06-28 07:33:14 -04:00
Web: improve custom cursor handling and add animated cursors (#3384)
This commit is contained in:
102
src/platform_impl/web/async/abortable.rs
Normal file
102
src/platform_impl/web/async/abortable.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
use std::error::Error;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use pin_project::pin_project;
|
||||
|
||||
use super::AtomicWaker;
|
||||
|
||||
#[pin_project]
|
||||
pub struct Abortable<F: Future> {
|
||||
#[pin]
|
||||
future: F,
|
||||
shared: Arc<Shared>,
|
||||
}
|
||||
|
||||
impl<F: Future> Abortable<F> {
|
||||
pub fn new(handle: AbortHandle, future: F) -> Self {
|
||||
Self {
|
||||
future,
|
||||
shared: handle.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Future> Future for Abortable<F> {
|
||||
type Output = Result<F::Output, Aborted>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
if self.shared.aborted.load(Ordering::Relaxed) {
|
||||
return Poll::Ready(Err(Aborted));
|
||||
}
|
||||
|
||||
if let Poll::Ready(value) = self.as_mut().project().future.poll(cx) {
|
||||
return Poll::Ready(Ok(value));
|
||||
}
|
||||
|
||||
self.shared.waker.register(cx.waker());
|
||||
|
||||
if self.shared.aborted.load(Ordering::Relaxed) {
|
||||
return Poll::Ready(Err(Aborted));
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Shared {
|
||||
waker: AtomicWaker,
|
||||
aborted: AtomicBool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AbortHandle(Arc<Shared>);
|
||||
|
||||
impl AbortHandle {
|
||||
pub fn new() -> Self {
|
||||
Self(Arc::new(Shared {
|
||||
waker: AtomicWaker::new(),
|
||||
aborted: AtomicBool::new(false),
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn abort(&self) {
|
||||
self.0.aborted.store(true, Ordering::Relaxed);
|
||||
self.0.waker.wake()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DropAbortHandle(AbortHandle);
|
||||
|
||||
impl DropAbortHandle {
|
||||
pub fn new(handle: AbortHandle) -> Self {
|
||||
Self(handle)
|
||||
}
|
||||
|
||||
pub fn handle(&self) -> AbortHandle {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DropAbortHandle {
|
||||
fn drop(&mut self) {
|
||||
self.0.abort()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct Aborted;
|
||||
|
||||
impl Display for Aborted {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "`Abortable` future has been aborted")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for Aborted {}
|
||||
Reference in New Issue
Block a user