windows_webview/
environment.rs1use super::*;
2
3pub struct Environment(pub(crate) ICoreWebView2Environment);
6
7impl Environment {
8 pub fn new() -> Result<Self> {
12 init_com()?;
13 let slot = pump::slot();
14 create_environment(pump::slot_handler(&slot))?;
15 pump::wait(&slot)
16 }
17
18 pub fn with_options(options: &EnvironmentOptions) -> Result<Self> {
20 init_com()?;
21 let slot = pump::slot();
22 options.create_environment(pump::slot_handler(&slot))?;
23 pump::wait(&slot)
24 }
25
26 pub fn create_controller(&self, window: &windows_window::Window) -> Result<Controller> {
28 unsafe { self.create_controller_for_hwnd(window.hwnd()) }
31 }
32
33 pub unsafe fn create_controller_for_hwnd(
39 &self,
40 parent: *mut core::ffi::c_void,
41 ) -> Result<Controller> {
42 let slot = pump::slot();
43 unsafe { self.create_controller_async(parent, pump::slot_handler(&slot))? };
44 pump::wait(&slot)
45 }
46
47 unsafe fn create_controller_async<F: FnOnce(Result<Controller>) + 'static>(
48 &self,
49 parent: HWND,
50 handler: F,
51 ) -> Result<()> {
52 let handler = handler::ControllerCompleted::create(handler);
53 unsafe { self.0.CreateCoreWebView2Controller(parent, &handler) }.ok()
54 }
55
56 pub fn create_controller_with_options(
58 &self,
59 window: &windows_window::Window,
60 options: &ControllerOptions,
61 ) -> Result<Controller> {
62 unsafe { self.create_controller_with_options_for_hwnd(window.hwnd(), options) }
65 }
66
67 pub unsafe fn create_controller_with_options_for_hwnd(
73 &self,
74 parent: *mut core::ffi::c_void,
75 options: &ControllerOptions,
76 ) -> Result<Controller> {
77 let slot = pump::slot();
78 options.create_controller(&self.0, parent, pump::slot_handler(&slot))?;
79 pump::wait(&slot)
80 }
81}
82
83fn create_environment<F: FnOnce(Result<Environment>) + 'static>(handler: F) -> Result<()> {
84 let handler = handler::EnvironmentCompleted::create(handler);
85 unsafe { CreateCoreWebView2Environment(Interface::as_raw(&handler)).ok() }
86}
87
88fn init_com() -> Result<()> {
89 let hr = unsafe { CoInitializeEx(std::ptr::null(), COINIT_APARTMENTTHREADED as u32) };
90 if hr == RPC_E_CHANGED_MODE {
91 return Err(Error::new(
92 RPC_E_CHANGED_MODE,
93 "windows_webview::Environment requires the calling thread to be a COM \
94 single-threaded apartment (STA), but it is already initialized as a \
95 multi-threaded apartment (MTA). Create the environment from a UI thread \
96 that has not called CoInitializeEx(COINIT_MULTITHREADED).",
97 ));
98 }
99 hr.ok()
100}