#[cfg(all(
feature = "webview-system",
target_os = "macos",
not(hydrolysis_macos_system_webview)
))]
compile_error!(
"the `webview-system` feature selects the macOS WKWebView bridge, which needs \
the `winit` feature (WKWebView is composed into the winit window's AppKit \
view). Enable `winit`, or link a browser engine crate \
(`waterui-browser-cef`, `waterui-browser-wpe`) in the application instead."
);
#[cfg(hydrolysis_macos_system_webview)]
use std::cell::RefCell;
#[cfg(hydrolysis_macos_system_webview)]
use std::rc::Rc;
use waterui_core::Environment;
use waterui_core::layout::Size as LayoutSize;
#[cfg(hydrolysis_macos_system_webview)]
use waterui_core::layout::{ProposalSize, ViewDimensions};
use waterui_webview::WebView;
#[cfg(hydrolysis_macos_system_webview)]
mod macos;
#[cfg(hydrolysis_macos_system_webview)]
pub use macos::MacSystemWebViewController;
use crate::renderer::{HydroNativeView, HydroState};
#[cfg(hydrolysis_macos_system_webview)]
use crate::renderer::{HydrolysisRenderer, WidgetRenderContext};
#[cfg(hydrolysis_macos_system_webview)]
pub(crate) struct WebViewRenderState {
_source: WebView,
native: macos::MacSystemWebViewHandle,
occlusion: Rc<RefCell<Vec<vello::kurbo::Rect>>>,
}
#[cfg(hydrolysis_macos_system_webview)]
impl WebViewRenderState {
pub(crate) fn from_view(view: WebView, env: &Environment) -> Self {
let _ = env;
let native = view
.handle()
.downcast_ref::<macos::MacSystemWebViewHandle>()
.unwrap_or_else(|| {
panic!("Hydrolysis macOS WebView handle does not use the selected system backend")
})
.clone();
Self {
_source: view,
native,
occlusion: Rc::new(RefCell::new(Vec::new())),
}
}
pub(crate) fn prebuild(
&mut self,
renderer: &mut crate::renderer::SemanticCore,
env: &Environment,
) {
let _ = (renderer, env);
}
}
impl HydroNativeView for WebView {
#[cfg(hydrolysis_macos_system_webview)]
fn intrinsic(
state: &mut HydroState,
view: &Self,
env: &Environment,
theme: &Rc<dyn crate::engine::WidgetTheme>,
) -> LayoutSize {
let _ = (state, view, env);
LayoutSize::zero()
}
#[cfg(hydrolysis_macos_system_webview)]
fn dimensions(
state: &mut HydroState,
view: &Self,
env: &Environment,
theme: &Rc<dyn crate::engine::WidgetTheme>,
proposal: ProposalSize,
) -> ViewDimensions {
let _ = (state, view, env);
ViewDimensions::new(LayoutSize::new(
proposal.width.unwrap_or(0.0),
proposal.height.unwrap_or(0.0),
))
}
#[cfg(not(hydrolysis_macos_system_webview))]
fn intrinsic(
_state: &mut HydroState,
_view: &Self,
_env: &Environment,
_theme: &std::rc::Rc<dyn crate::engine::WidgetTheme>,
) -> LayoutSize {
crate::renderer::unsupported_webview()
}
}
#[cfg(hydrolysis_macos_system_webview)]
pub(crate) fn measure_webview_node(
state: &WebViewRenderState,
proposal: ProposalSize,
hydro: &mut HydroState,
_env: &Environment,
theme: &Rc<dyn crate::engine::WidgetTheme>,
) -> ViewDimensions {
let _ = (state, hydro);
ViewDimensions::new(LayoutSize::new(
proposal.width.unwrap_or(0.0),
proposal.height.unwrap_or(0.0),
))
}
#[cfg(hydrolysis_macos_system_webview)]
pub(crate) fn render_webview_node(
ctx: &mut WidgetRenderContext<'_>,
state: &Rc<RefCell<WebViewRenderState>>,
env: &Environment,
) {
super::register_web_surface_accessibility(ctx, env);
use crate::renderer::transformed_rect;
let bounds = ctx.bounds;
let transform = ctx.render_context().transform;
let hit_transform = ctx.hit_transform;
let (native, occlusion) = {
let state = state.borrow();
(state.native.native_view(), Rc::clone(&state.occlusion))
};
let renderer = ctx.renderer_mut();
renderer.register_native_view_occlusion(
transformed_rect(hit_transform, bounds),
Rc::clone(&occlusion),
);
renderer.record_native_view_layer(native, transform, bounds, occlusion);
}
#[cfg(hydrolysis_macos_system_webview)]
pub(crate) fn install_controller(env: &mut Environment) {
macos::install(env);
}