1use blitz_traits::navigation::NavigationOptions;
2use blitz_traits::net::NetWaker;
3use futures_util::task::ArcWake;
4use std::sync::mpsc::{Receiver, Sender, channel};
5use std::{any::Any, sync::Arc};
6use winit::{event_loop::EventLoopProxy, window::WindowId};
7
8#[cfg(feature = "accessibility")]
9use accesskit_xplat::WindowEvent as AccessKitEvent;
10
11#[derive(Debug, Clone)]
12pub enum BlitzShellEvent {
13 Poll {
14 window_id: WindowId,
15 },
16
17 ResumeReady {
21 window_id: WindowId,
22 },
23
24 RequestRedraw {
25 doc_id: usize,
26 },
27
28 CloseWindow {
31 window_id: WindowId,
32 },
33
34 #[cfg(feature = "accessibility")]
36 Accessibility {
37 window_id: WindowId,
38 data: Arc<AccessKitEvent>,
39 },
40
41 Embedder(Arc<dyn Any + Send + Sync>),
43
44 Navigate(Box<NavigationOptions>),
46
47 NavigationLoad {
49 url: String,
50 contents: String,
51 retain_scroll_position: bool,
52 is_md: bool,
53 },
54
55 #[cfg(target_arch = "wasm32")]
59 ResizeSettleCheck {
60 window_id: WindowId,
61 },
62}
63impl BlitzShellEvent {
64 pub fn embedder_event<T: Any + Send + Sync>(value: T) -> Self {
65 let boxed = Arc::new(value) as Arc<dyn Any + Send + Sync>;
66 Self::Embedder(boxed)
67 }
68}
69
70#[derive(Clone)]
71pub struct BlitzShellProxy(Arc<BlitzShellProxyInner>);
72pub struct BlitzShellProxyInner {
73 winit_proxy: EventLoopProxy,
74 sender: Sender<BlitzShellEvent>,
75}
76
77impl BlitzShellProxy {
78 pub fn new(winit_proxy: EventLoopProxy) -> (Self, Receiver<BlitzShellEvent>) {
79 let (sender, receiver) = channel();
80 let proxy = Self(Arc::new(BlitzShellProxyInner {
81 winit_proxy,
82 sender,
83 }));
84 (proxy, receiver)
85 }
86
87 pub fn wake_up(&self) {
88 self.0.winit_proxy.wake_up();
89 }
90 pub fn send_event(&self, event: impl Into<BlitzShellEvent>) {
91 self.send_event_impl(event.into());
92 }
93 fn send_event_impl(&self, event: BlitzShellEvent) {
94 let _ = self.0.sender.send(event);
95 self.wake_up();
96 }
97}
98
99impl NetWaker for BlitzShellProxy {
100 fn wake(&self, client_id: usize) {
101 self.send_event_impl(BlitzShellEvent::RequestRedraw { doc_id: client_id })
102 }
103}
104
105pub fn create_waker(proxy: &BlitzShellProxy, id: WindowId) -> std::task::Waker {
111 struct DomHandle {
112 proxy: BlitzShellProxy,
113 id: WindowId,
114 }
115 impl ArcWake for DomHandle {
116 fn wake_by_ref(arc_self: &Arc<Self>) {
117 let event = BlitzShellEvent::Poll {
118 window_id: arc_self.id,
119 };
120 arc_self.proxy.send_event(event)
121 }
122 }
123
124 let proxy = proxy.clone();
125 futures_util::task::waker(Arc::new(DomHandle { id, proxy }))
126}