blitz_shell/
application.rs1use crate::event::BlitzShellEvent;
2
3use anyrender::WindowRenderer;
4use std::collections::HashMap;
5use winit::application::ApplicationHandler;
6use winit::event::WindowEvent;
7use winit::event_loop::{ActiveEventLoop, EventLoopProxy};
8use winit::window::WindowId;
9
10use crate::{View, WindowConfig};
11
12pub struct BlitzApplication<Rend: WindowRenderer> {
13 pub windows: HashMap<WindowId, View<Rend>>,
14 pub pending_windows: Vec<WindowConfig<Rend>>,
15 pub proxy: EventLoopProxy<BlitzShellEvent>,
16}
17
18impl<Rend: WindowRenderer> BlitzApplication<Rend> {
19 pub fn new(proxy: EventLoopProxy<BlitzShellEvent>) -> Self {
20 BlitzApplication {
21 windows: HashMap::new(),
22 pending_windows: Vec::new(),
23 proxy,
24 }
25 }
26
27 pub fn add_window(&mut self, window_config: WindowConfig<Rend>) {
28 self.pending_windows.push(window_config);
29 }
30
31 fn window_mut_by_doc_id(&mut self, doc_id: usize) -> Option<&mut View<Rend>> {
32 self.windows.values_mut().find(|w| w.doc.id() == doc_id)
33 }
34}
35
36impl<Rend: WindowRenderer> ApplicationHandler<BlitzShellEvent> for BlitzApplication<Rend> {
37 fn resumed(&mut self, event_loop: &ActiveEventLoop) {
38 for (_, view) in self.windows.iter_mut() {
40 view.resume();
41 }
42
43 for window_config in self.pending_windows.drain(..) {
45 let mut view = View::init(window_config, event_loop, &self.proxy);
46 view.resume();
47 if !view.renderer.is_active() {
48 continue;
49 }
50 self.windows.insert(view.window_id(), view);
51 }
52 }
53
54 fn suspended(&mut self, _event_loop: &ActiveEventLoop) {
55 for (_, view) in self.windows.iter_mut() {
56 view.suspend();
57 }
58 }
59
60 fn window_event(
61 &mut self,
62 event_loop: &ActiveEventLoop,
63 window_id: WindowId,
64 event: WindowEvent,
65 ) {
66 if matches!(event, WindowEvent::CloseRequested) {
68 let window = self.windows.remove(&window_id);
71 drop(window);
72 if self.windows.is_empty() {
73 event_loop.exit();
74 }
75 return;
76 }
77
78 if let Some(window) = self.windows.get_mut(&window_id) {
79 window.handle_winit_event(event);
80 }
81
82 let _ = self.proxy.send_event(BlitzShellEvent::Poll { window_id });
83 }
84
85 fn user_event(&mut self, _event_loop: &ActiveEventLoop, event: BlitzShellEvent) {
86 match event {
87 BlitzShellEvent::Poll { window_id } => {
88 if let Some(window) = self.windows.get_mut(&window_id) {
89 window.poll();
90 };
91 }
92 BlitzShellEvent::ResourceLoad { doc_id, data } => {
93 if let Some(window) = self.window_mut_by_doc_id(doc_id) {
95 window.doc.as_mut().load_resource(data);
96 window.request_redraw();
97 }
98 }
99
100 #[cfg(feature = "accessibility")]
101 BlitzShellEvent::Accessibility { window_id, data } => {
102 if let Some(window) = self.windows.get_mut(&window_id) {
103 match &*data {
104 accesskit_winit::WindowEvent::InitialTreeRequested => {
105 window.build_accessibility_tree();
106 }
107 accesskit_winit::WindowEvent::AccessibilityDeactivated => {
108 }
110 accesskit_winit::WindowEvent::ActionRequested(_req) => {
111 }
113 }
114 }
115 }
116
117 BlitzShellEvent::Embedder(_) => {
118 }
120 BlitzShellEvent::Navigate(_opts) => {
121 }
123 BlitzShellEvent::NavigationLoad { .. } => {
124 }
126 }
127 }
128}