use std::{any::Any, fmt};
#[cfg(any(feature = "webview-cef", feature = "cef-header"))]
use waterui_browser_cef::CefWebViewHandle;
use waterui_browser_cef::{
CefPageHandle, CefRuntime, CefRuntimeConfiguration, gpu_view_with_input,
};
#[cfg(any(feature = "chromium", feature = "cef-header"))]
use waterui_chromium::{ChromiumView, PageMode};
use waterui_core::Environment;
use waterui_graphics::gpu_surface::GpuSurface;
#[cfg(any(feature = "webview-cef", feature = "cef-header"))]
use waterui_webview::WebView;
#[cfg(any(feature = "webview-cef", feature = "cef-header"))]
use crate::WuiAnyView;
use crate::components::visual::gpu_surface::WuiGpuSurface;
use crate::{IntoFFI, IntoRust};
pub(crate) fn configure_environment(env: &mut Environment) {
let runtime = CefRuntime::initialize(CefRuntimeConfiguration::packaged());
#[cfg(any(feature = "webview-cef", feature = "cef-header"))]
env.insert(runtime.webview_controller());
#[cfg(any(feature = "chromium", feature = "cef-header"))]
env.insert(runtime.chromium_controller());
env.insert(runtime.clone());
runtime.start_message_pump();
}
#[repr(C)]
#[derive(Debug)]
pub struct WuiCefSurface {
pub gpu_surface: WuiGpuSurface,
pub state: *mut WuiCefSurfaceState,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum WuiCefEditCommand {
Undo,
Redo,
Cut,
Copy,
Paste,
SelectAll,
}
pub struct WuiCefSurfaceState {
page: CefPageHandle,
_source: Box<dyn Any>,
}
impl fmt::Debug for WuiCefSurfaceState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("WuiCefSurfaceState").finish_non_exhaustive()
}
}
fn surface(page: CefPageHandle, source: impl Any) -> WuiCefSurface {
let gpu_surface = GpuSurface::new(gpu_view_with_input(page.clone())).into_ffi();
WuiCefSurface {
gpu_surface,
state: Box::into_raw(Box::new(WuiCefSurfaceState {
page,
_source: Box::new(source),
})),
}
}
#[cfg(any(feature = "chromium", feature = "cef-header"))]
impl IntoFFI for ChromiumView {
type FFI = WuiCefSurface;
fn into_ffi(self) -> Self::FFI {
assert_eq!(
self.page().mode(),
PageMode::Visible,
"headless Chromium pages cannot be rendered as ChromiumView"
);
let page = self
.page()
.handle()
.downcast_ref::<CefPageHandle>()
.unwrap_or_else(|| {
panic!("Apple ChromiumView handle does not use the selected CEF runtime")
})
.clone();
surface(page, self)
}
}
#[cfg(any(feature = "chromium", feature = "cef-header"))]
ffi_view!(ChromiumView, WuiCefSurface, chromium, any());
#[cfg(any(feature = "webview-cef", feature = "cef-header"))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_force_as_cef_webview(view: *mut WuiAnyView) -> WuiCefSurface {
let any: waterui::AnyView = unsafe { IntoRust::into_rust(view) };
let view = unsafe { *any.downcast_unchecked::<waterui_core::Native<WebView>>() }.into_inner();
let page = view
.handle()
.downcast_ref::<CefWebViewHandle>()
.unwrap_or_else(|| panic!("Apple WebView handle does not use the selected CEF runtime"))
.page()
.clone();
surface(page, view)
}
const unsafe fn borrow_state<'a>(state: *const WuiCefSurfaceState) -> &'a WuiCefSurfaceState {
unsafe { crate::borrow_ffi(state) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_cef_surface_go_back(state: *const WuiCefSurfaceState) {
unsafe { borrow_state(state) }.page.go_back();
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_cef_surface_go_forward(state: *const WuiCefSurfaceState) {
unsafe { borrow_state(state) }.page.go_forward();
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_cef_surface_edit(
state: *const WuiCefSurfaceState,
command: WuiCefEditCommand,
) {
let page = &unsafe { borrow_state(state) }.page;
match command {
WuiCefEditCommand::Undo => page.undo(),
WuiCefEditCommand::Redo => page.redo(),
WuiCefEditCommand::Cut => page.cut(),
WuiCefEditCommand::Copy => page.copy(),
WuiCefEditCommand::Paste => page.paste(),
WuiCefEditCommand::SelectAll => page.select_all(),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn waterui_cef_surface_drop(state: *mut WuiCefSurfaceState) {
drop(unsafe { Box::from_raw(state) });
}
#[cfg(target_os = "macos")]
#[unsafe(no_mangle)]
pub extern "C" fn waterui_cef_prepare_macos_application() {
waterui_browser_cef::initialize_macos_application();
}
#[cfg(target_os = "macos")]
#[unsafe(no_mangle)]
pub extern "C" fn waterui_cef_run_packaged_subprocess() -> i32 {
waterui_browser_cef::run_packaged_subprocess()
}