browser_window/core/application/
c.rs

1//! This module implements the `Application` trait with the corresponding
2//! function definitions found in the C code base of `browser-window-c`.
3//! All functions are basically wrapping the FFI provided by crate
4//! `browser-window-c`.
5
6use std::{
7	os::raw::{c_char, c_int, c_void},
8	path::PathBuf,
9	ptr,
10	time::Duration,
11};
12
13use super::{ApplicationExt, ApplicationSettings};
14use crate::{error::*, prelude::*};
15
16#[derive(Clone, Copy)]
17pub struct ApplicationImpl {
18	pub(crate) inner: *mut cbw_Application,
19}
20
21impl ApplicationExt for ApplicationImpl {
22	fn assert_correct_thread(&self) { unsafe { cbw_Application_assertCorrectThread(self.inner) } }
23
24	fn dispatch(&self, work: fn(ApplicationImpl, *mut ()), _data: *mut ()) -> bool {
25		let data = Box::new(DispatchData {
26			func: work,
27			data: _data,
28		});
29
30		let data_ptr = Box::into_raw(data);
31
32		unsafe {
33			cbw_Application_dispatch(self.inner, Some(invocation_handler), data_ptr as _) != 0
34		}
35	}
36
37	fn dispatch_delayed(
38		&self, work: fn(ApplicationImpl, *mut ()), _data: *mut (), delay: Duration,
39	) -> bool {
40		let data = Box::new(DispatchData {
41			func: work,
42			data: _data,
43		});
44
45		let data_ptr = Box::into_raw(data);
46
47		unsafe {
48			cbw_Application_dispatchDelayed(
49				self.inner,
50				Some(invocation_handler),
51				data_ptr as _,
52				delay.as_millis() as _,
53			) != 0
54		}
55	}
56
57	fn exit(&self, exit_code: i32) { unsafe { cbw_Application_exit(self.inner, exit_code as _) } }
58
59	fn exit_threadsafe(self: &Self, exit_code: i32) {
60		unsafe { cbw_Application_exitAsync(self.inner, exit_code) }
61	}
62
63	fn initialize(
64		argc: c_int, argv: *mut *mut c_char, settings: &ApplicationSettings,
65	) -> Result<Self> {
66		let exec_path: &str = match settings.engine_seperate_executable_path.as_ref() {
67			None => "",
68			Some(path) => path.to_str().unwrap(),
69		};
70
71		let c_settings = cbw_ApplicationSettings {
72			engine_seperate_executable_path: exec_path.into(),
73			resource_dir: settings
74				.resource_dir
75				.as_ref()
76				.unwrap_or(&PathBuf::new())
77				.as_os_str()
78				.to_string_lossy()
79				.as_ref()
80				.into(),
81			remote_debugging_port: settings.remote_debugging_port.unwrap_or(0),
82		};
83
84		let mut c_handle: *mut cbw_Application = ptr::null_mut();
85		let c_err = unsafe { cbw_Application_initialize(&mut c_handle, argc, argv, &c_settings) };
86		if c_err.code != 0 {
87			return Err(c_err.into());
88		}
89
90		Ok(Self { inner: c_handle })
91	}
92
93	fn mark_as_done(&self) { unsafe { cbw_Application_markAsDone(self.inner) }; }
94
95	fn run(&self, on_ready: fn(ApplicationImpl, *mut ()), _data: *mut ()) -> i32 {
96		let data = Box::new(DispatchData {
97			func: on_ready,
98			data: _data,
99		});
100
101		let data_ptr = Box::into_raw(data);
102
103		// The dispatch handler does exactly the same thing
104		unsafe { cbw_Application_run(self.inner, Some(invocation_handler), data_ptr as _) }
105	}
106}
107
108struct DispatchData {
109	func: unsafe fn(ApplicationImpl, *mut ()),
110	data: *mut (),
111}
112
113unsafe extern "C" fn invocation_handler(_handle: *mut cbw_Application, _data: *mut c_void) {
114	let data_ptr = _data as *mut DispatchData;
115	let data = Box::from_raw(data_ptr);
116	let handle = ApplicationImpl { inner: _handle };
117
118	(data.func)(handle, data.data);
119}