Skip to main content

orinium_browser/platform/system/
app.rs

1//! Manages the application lifecycle, including window creation and event handling.
2
3use 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        // 初回描画
114        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}