1use blitz_traits::navigation::NavigationOptions;
2use futures_util::task::ArcWake;
3use std::{any::Any, sync::Arc};
4use winit::{event_loop::EventLoopProxy, window::WindowId};
5
6#[cfg(feature = "accessibility")]
7use accesskit_winit::{Event as AccessKitEvent, WindowEvent as AccessKitWindowEvent};
8use blitz_dom::net::Resource;
9
10#[derive(Debug, Clone)]
11pub enum BlitzShellEvent {
12 Poll {
13 window_id: WindowId,
14 },
15
16 ResourceLoad {
17 doc_id: usize,
18 data: Resource,
19 },
20
21 #[cfg(feature = "accessibility")]
23 Accessibility {
24 window_id: WindowId,
25 data: Arc<AccessKitWindowEvent>,
26 },
27
28 Embedder(Arc<dyn Any + Send + Sync>),
30
31 Navigate(Box<NavigationOptions>),
33
34 NavigationLoad {
36 url: String,
37 contents: String,
38 retain_scroll_position: bool,
39 is_md: bool,
40 },
41}
42impl BlitzShellEvent {
43 pub fn embedder_event<T: Any + Send + Sync>(value: T) -> Self {
44 let boxed = Arc::new(value) as Arc<dyn Any + Send + Sync>;
45 Self::Embedder(boxed)
46 }
47}
48impl From<(usize, Resource)> for BlitzShellEvent {
49 fn from((doc_id, data): (usize, Resource)) -> Self {
50 BlitzShellEvent::ResourceLoad { doc_id, data }
51 }
52}
53
54#[cfg(feature = "accessibility")]
55impl From<AccessKitEvent> for BlitzShellEvent {
56 fn from(value: AccessKitEvent) -> Self {
57 Self::Accessibility {
58 window_id: value.window_id,
59 data: Arc::new(value.window_event),
60 }
61 }
62}
63
64pub fn create_waker(proxy: &EventLoopProxy<BlitzShellEvent>, id: WindowId) -> std::task::Waker {
70 struct DomHandle {
71 proxy: EventLoopProxy<BlitzShellEvent>,
72 id: WindowId,
73 }
74
75 unsafe impl Send for DomHandle {}
78 unsafe impl Sync for DomHandle {}
79
80 impl ArcWake for DomHandle {
81 fn wake_by_ref(arc_self: &Arc<Self>) {
82 _ = arc_self.proxy.send_event(BlitzShellEvent::Poll {
83 window_id: arc_self.id,
84 })
85 }
86 }
87
88 futures_util::task::waker(Arc::new(DomHandle {
89 id,
90 proxy: proxy.clone(),
91 }))
92}