orinium_browser/platform/system/
app.rs1use std::collections::HashMap;
4use std::sync::Arc;
5use winit::application::ApplicationHandler;
6use winit::event::WindowEvent;
7use winit::event_loop::ActiveEventLoop;
8use winit::window::{Window, WindowId};
9
10use crate::browser::{BrowserApp, BrowserCommand, BrowserUi, Tab};
11use crate::platform::renderer::gpu::GpuRenderer;
12
13pub struct WindowState {
14 pub window: Arc<Window>,
15 pub gpu_renderer: GpuRenderer,
16}
17
18pub struct App {
19 windows: HashMap<WindowId, WindowState>,
20 browser_app: BrowserApp,
21}
22
23impl App {
24 pub fn new(browser_app: BrowserApp) -> Self {
25 Self {
26 windows: HashMap::new(),
27 browser_app,
28 }
29 }
30
31 fn open_new_window(&mut self, event_loop: &ActiveEventLoop) {
32 let default_size = self.browser_app.default_window_size();
33 let default_title = self.browser_app.default_window_title();
34 let window = Arc::new(
35 event_loop
36 .create_window(
37 Window::default_attributes()
38 .with_inner_size(winit::dpi::PhysicalSize::new(
39 default_size.0,
40 default_size.1,
41 ))
42 .with_title(&default_title),
43 )
44 .unwrap(),
45 );
46 let window_id = window.id();
47 let initial_size = window.inner_size();
48 let scale_factor = window.scale_factor();
49 let gpu_renderer = pollster::block_on(GpuRenderer::new(Arc::clone(&window), None)).unwrap();
50
51 let root_ui = BrowserUi::with_tab(Tab::default());
52
53 self.browser_app.open_window(
54 window_id,
55 (initial_size.width, initial_size.height),
56 default_title,
57 scale_factor,
58 root_ui,
59 );
60
61 let mut state = WindowState {
62 window,
63 gpu_renderer,
64 };
65
66 self.browser_app
67 .apply_draw_commands(window_id, &mut state.gpu_renderer);
68 state.window.request_redraw();
69
70 self.windows.insert(window_id, state);
71 }
72}
73
74impl ApplicationHandler for App {
75 fn resumed(&mut self, event_loop: &ActiveEventLoop) {
76 let default_size = self.browser_app.default_window_size();
77 let default_title = self.browser_app.default_window_title();
78 let window = Arc::new(
79 event_loop
80 .create_window(
81 Window::default_attributes()
82 .with_inner_size(winit::dpi::PhysicalSize::new(
83 default_size.0,
84 default_size.1,
85 ))
86 .with_title(&default_title),
87 )
88 .unwrap(),
89 );
90 let window_id = window.id();
91 let initial_size = window.inner_size();
92 let scale_factor = window.scale_factor();
93 let gpu_renderer = pollster::block_on(GpuRenderer::new(Arc::clone(&window), None)).unwrap();
94
95 let Some(root_ui) = self.browser_app.take_default_ui() else {
96 log::error!("BrowserApp has no default UI configured");
97 return;
98 };
99
100 self.browser_app.open_window(
101 window_id,
102 (initial_size.width, initial_size.height),
103 default_title,
104 scale_factor,
105 root_ui,
106 );
107
108 let mut state = WindowState {
109 window,
110 gpu_renderer,
111 };
112
113 self.browser_app
115 .apply_draw_commands(window_id, &mut state.gpu_renderer);
116 state.window.request_redraw();
117
118 self.windows.insert(window_id, state);
119 }
120
121 fn window_event(
122 &mut self,
123 event_loop: &ActiveEventLoop,
124 window_id: WindowId,
125 event: WindowEvent,
126 ) {
127 if !self.windows.contains_key(&window_id) {
128 return;
129 }
130
131 let cmd = {
132 let state = self.windows.get_mut(&window_id).unwrap();
133 self.browser_app
134 .handle_window_event(window_id, event, &mut state.gpu_renderer)
135 };
136
137 match cmd {
138 BrowserCommand::Exit => {
139 self.windows.remove(&window_id);
140 self.browser_app.close_window(window_id);
141 if self.windows.is_empty() {
142 event_loop.exit();
143 }
144 }
145 BrowserCommand::RequestRedraw => {
146 if let Some(state) = self.windows.get(&window_id) {
147 state.window.request_redraw();
148 state
149 .window
150 .set_title(&self.browser_app.window_title(window_id));
151 }
152 }
153 BrowserCommand::RenameWindowTitle => {
154 if let Some(state) = self.windows.get(&window_id) {
155 state
156 .window
157 .set_title(&self.browser_app.window_title(window_id));
158 }
159 }
160 BrowserCommand::OpenNewWindow => {
161 self.open_new_window(event_loop);
162 }
163 BrowserCommand::SetImeAllowed { allowed, position } => {
164 if let Some(state) = self.windows.get(&window_id) {
165 state.window.set_ime_allowed(allowed);
166 if allowed {
167 state.window.set_ime_cursor_area(
168 winit::dpi::PhysicalPosition::new(position.0, position.1 + 24.0),
169 winit::dpi::PhysicalSize::new(1.0, 1.0),
170 );
171 }
172 state.window.request_redraw();
173 }
174 }
175 BrowserCommand::None => {}
176 }
177 }
178
179 fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
180 let window_ids: Vec<WindowId> = self.windows.keys().copied().collect();
181 for window_id in window_ids {
182 if self.browser_app.poll_window(window_id)
183 && let Some(state) = self.windows.get(&window_id)
184 {
185 state.window.request_redraw();
186 }
187 }
188 }
189}