use dioxus::dioxus_core::{Runtime, ScopeId, queue_effect}; use dioxus::html::geometry::ClientPoint; use dioxus::prelude::*; #[derive(Debug)] pub struct Pointer { pub id: i32, pub position: ClientPoint, } pub static POINTERS: GlobalSignal> = Global::new(|| { let runtime = Runtime::current(); queue_effect(move || { runtime.spawn(ScopeId::ROOT, async move { let mut pointer_updates = dioxus::document::eval( "window.addEventListener('pointerdown', (e) => { dioxus.send(['down', [e.pointerId, e.clientX, e.clientY]]); }); window.addEventListener('pointermove', (e) => { dioxus.send(['move', [e.pointerId, e.clientX, e.clientY]]); }); window.addEventListener('pointerup', (e) => { dioxus.send(['up', [e.pointerId, e.clientX, e.clientY]]); });", ); while let Ok((event_type, (pointer_id, x, y))) = pointer_updates.recv::<(String, (i32, f64, f64))>().await { let position = ClientPoint::new(x, y); match event_type.as_str() { "down" => { let mut ptrs = POINTERS.write(); if !ptrs.iter().any(|p| p.id == pointer_id) { ptrs.push(Pointer { id: pointer_id, position, }); } } "move" => { if let Some(pointer) = POINTERS.write().iter_mut().find(|p| p.id == pointer_id) { pointer.position = position; } } "up" => { POINTERS.write().retain(|p| p.id != pointer_id); } _ => {} } } }); }); Vec::new() }); /// Get the current position of a tracked pointer, or `None` if it's not active. pub fn pointer_position(id: i32) -> Option { POINTERS .read() .iter() .find(|p| p.id == id) .map(|p| p.position) }