browser_window/browser/
builder.rs1use std::{ops::DerefMut, path::PathBuf};
2
3#[cfg(feature = "threadsafe")]
4use unsafe_send_sync::UnsafeSend;
5
6use crate::{
7 application::ApplicationHandle,
8 browser::*,
9 core::{browser_window::*, window::*},
10 rc::Rc,
11 window::WindowBuilder,
12};
13
14#[derive(Clone)]
16pub enum Source {
17 Html(String),
19 File(PathBuf),
21 Url(String),
23}
24
25pub struct BrowserWindowBuilder {
35 dev_tools: bool,
36 source: Source,
37 window: WindowBuilder,
38}
39
40impl BrowserWindowBuilder {
41 pub fn dev_tools(&mut self, enabled: bool) -> &mut Self {
45 self.dev_tools = enabled;
46 self
47 }
48
49 pub fn new(source: Source) -> Self {
54 Self {
55 dev_tools: false,
56 source,
57 window: WindowBuilder::new(),
58 }
59 }
60
61 #[deprecated(since = "0.12.1", note = "please use `build_async` instead")]
62 pub async fn build(self, app: &ApplicationHandle) -> BrowserWindow {
63 self.build_async(app).await
64 }
65
66 pub async fn build_async(self, app: &ApplicationHandle) -> BrowserWindow {
71 let (tx, rx) = oneshot::channel::<BrowserWindowHandle>();
72
73 self._build(app, move |handle| {
74 if let Err(_) = tx.send(handle) {
75 panic!("Unable to send browser handle back")
76 }
77 });
78
79 Self::prepare_handle(rx.await.unwrap())
80 }
81
82 #[cfg(feature = "threadsafe")]
93 pub async fn build_threaded(
94 self, app: &ApplicationHandleThreaded,
95 ) -> Result<BrowserWindowThreaded, DelegateError> {
96 let (tx, rx) = oneshot::channel::<UnsafeSend<BrowserWindowHandle>>();
97
98 app.delegate(|app_handle| {
100 self._build(&*app_handle, |inner_handle| {
101 if let Err(_) = tx.send(UnsafeSend::new(inner_handle)) {
102 panic!("Unable to send browser handle back")
103 }
104 });
105 })
106 .await?;
107
108 Ok(BrowserWindowThreaded(Self::prepare_handle(
109 rx.await.unwrap().unwrap(),
110 )))
111 }
112
113 fn prepare_handle(handle: BrowserWindowHandle) -> BrowserWindow {
114 let owner = BrowserWindowOwner(handle);
117 let rc_handle = Rc::new(owner);
118 let user_data = Box::into_raw(Box::new(BrowserUserData {
119 _handle: rc_handle.clone(),
120 }));
121 rc_handle.0.window().0.set_user_data(user_data as _);
122
123 BrowserWindow(rc_handle)
124 }
125
126 pub fn build_sync(self, app: &ApplicationHandle, on_created: impl FnOnce(BrowserWindow)) {
127 self._build(app, move |inner| {
128 let handle = Self::prepare_handle(inner);
129 on_created(handle);
130 })
131 }
132
133 fn _build(self, app: &ApplicationHandle, on_created: impl FnOnce(BrowserWindowHandle)) {
134 match self {
135 Self {
136 source,
137 dev_tools,
138 window,
139 } => {
140 let parent_handle = match window.parent {
142 None => WindowImpl::default(),
143 Some(p) => p.i,
144 };
145
146 let title = match window.title.as_ref() {
148 None => "Browser Window".into(),
149 Some(t) => t.as_str().into(),
150 };
151
152 let callback_data: *mut Box<dyn FnOnce(BrowserWindowHandle)> =
153 Box::into_raw(Box::new(Box::new(on_created)));
154
155 let window_options = WindowOptions {
157 borders: window.borders,
158 minimizable: window.minimizable,
159 resizable: window.resizable,
160 };
161 let other_options = BrowserWindowOptions {
162 dev_tools: if dev_tools { 1 } else { 0 },
163 resource_path: "".into(),
164 };
165
166 BrowserWindowImpl::new(
167 app.inner.clone(),
168 parent_handle,
169 source,
170 title,
171 window.width,
172 window.height,
173 &window_options,
174 &other_options,
175 browser_window_created_callback,
176 callback_data as _,
177 );
178 }
179 }
180 }
181}
182
183impl Deref for BrowserWindowBuilder {
184 type Target = WindowBuilder;
185
186 fn deref(&self) -> &Self::Target { &self.window }
187}
188
189impl DerefMut for BrowserWindowBuilder {
190 fn deref_mut(&mut self) -> &mut Self::Target { &mut self.window }
191}
192
193fn browser_window_created_callback(inner_handle: BrowserWindowImpl, data: *mut ()) {
194 let data_ptr = data as *mut Box<dyn FnOnce(&BrowserWindowHandle)>;
195 let func = unsafe { Box::from_raw(data_ptr) };
196
197 let rust_handle = BrowserWindowHandle::new(inner_handle);
198
199 func(&rust_handle);
200}