1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3mod application;
12mod convert_events;
13mod event;
14mod net;
15mod window;
16
17#[cfg(feature = "accessibility")]
18mod accessibility;
19
20pub use crate::application::BlitzApplication;
21pub use crate::event::BlitzShellEvent;
22pub use crate::net::BlitzShellNetCallback;
23pub use crate::window::{View, WindowConfig};
24
25#[cfg(feature = "data-uri")]
26pub use crate::net::DataUriNetProvider;
27
28#[cfg(all(
29 feature = "file_dialog",
30 any(
31 target_os = "windows",
32 target_os = "macos",
33 target_os = "linux",
34 target_os = "dragonfly",
35 target_os = "freebsd",
36 target_os = "netbsd",
37 target_os = "openbsd"
38 )
39))]
40use blitz_traits::shell::FileDialogFilter;
41use blitz_traits::shell::ShellProvider;
42use std::sync::Arc;
43pub use winit::event_loop::{ControlFlow, EventLoop, EventLoopProxy};
44pub use winit::window::{CursorIcon, Window};
45
46#[derive(Default)]
47pub struct Config {
48 pub stylesheets: Vec<String>,
49 pub base_url: Option<String>,
50}
51
52pub fn create_default_event_loop<Event>() -> EventLoop<Event> {
54 let mut ev_builder = EventLoop::<Event>::with_user_event();
55 #[cfg(target_os = "android")]
56 {
57 use winit::platform::android::EventLoopBuilderExtAndroid;
58 ev_builder.with_android_app(current_android_app());
59 }
60
61 let event_loop = ev_builder.build().unwrap();
62 event_loop.set_control_flow(ControlFlow::Wait);
63
64 event_loop
65}
66
67#[cfg(target_os = "android")]
68static ANDROID_APP: std::sync::OnceLock<android_activity::AndroidApp> = std::sync::OnceLock::new();
69
70#[cfg(target_os = "android")]
71#[cfg_attr(docsrs, doc(cfg(target_os = "android")))]
72pub fn set_android_app(app: android_activity::AndroidApp) {
74 ANDROID_APP.set(app).unwrap()
75}
76
77#[cfg(target_os = "android")]
78#[cfg_attr(docsrs, doc(cfg(target_os = "android")))]
79pub fn current_android_app() -> android_activity::AndroidApp {
82 ANDROID_APP.get().unwrap().clone()
83}
84
85pub struct BlitzShellProvider {
86 window: Arc<Window>,
87}
88impl BlitzShellProvider {
89 pub fn new(window: Arc<Window>) -> Self {
90 Self { window }
91 }
92}
93
94impl ShellProvider for BlitzShellProvider {
95 fn request_redraw(&self) {
96 self.window.request_redraw();
97 }
98 fn set_cursor(&self, icon: CursorIcon) {
99 self.window.set_cursor(icon);
100 }
101 fn set_window_title(&self, title: String) {
102 self.window.set_title(&title);
103 }
104
105 #[cfg(all(
106 feature = "clipboard",
107 any(
108 target_os = "windows",
109 target_os = "macos",
110 target_os = "linux",
111 target_os = "dragonfly",
112 target_os = "freebsd",
113 target_os = "netbsd",
114 target_os = "openbsd"
115 )
116 ))]
117 fn get_clipboard_text(&self) -> Result<String, blitz_traits::shell::ClipboardError> {
118 let mut cb = arboard::Clipboard::new().unwrap();
119 cb.get_text()
120 .map_err(|_| blitz_traits::shell::ClipboardError)
121 }
122
123 #[cfg(all(
124 feature = "clipboard",
125 any(
126 target_os = "windows",
127 target_os = "macos",
128 target_os = "linux",
129 target_os = "dragonfly",
130 target_os = "freebsd",
131 target_os = "netbsd",
132 target_os = "openbsd"
133 )
134 ))]
135 fn set_clipboard_text(&self, text: String) -> Result<(), blitz_traits::shell::ClipboardError> {
136 let mut cb = arboard::Clipboard::new().unwrap();
137 cb.set_text(text.to_owned())
138 .map_err(|_| blitz_traits::shell::ClipboardError)
139 }
140
141 #[cfg(all(
142 feature = "file_dialog",
143 any(
144 target_os = "windows",
145 target_os = "macos",
146 target_os = "linux",
147 target_os = "dragonfly",
148 target_os = "freebsd",
149 target_os = "netbsd",
150 target_os = "openbsd"
151 )
152 ))]
153 fn open_file_dialog(
154 &self,
155 multiple: bool,
156 filter: Option<FileDialogFilter>,
157 ) -> Vec<std::path::PathBuf> {
158 let mut dialog = rfd::FileDialog::new();
159 if let Some(FileDialogFilter { name, extensions }) = filter {
160 dialog = dialog.add_filter(&name, &extensions);
161 }
162 let files = if multiple {
163 dialog.pick_files()
164 } else {
165 dialog.pick_file().map(|file| vec![file])
166 };
167 files.unwrap_or_default()
168 }
169}