new window opener

This commit is contained in:
Lucas Nogueira 2026-01-26 09:54:45 -03:00
parent fc405b3ae6
commit 98fdc7c5fa
No known key found for this signature in database
7 changed files with 321 additions and 177 deletions

View File

@ -608,6 +608,7 @@ wrap_life_span_handler! {
window_kind: WindowKind,
window_id: WindowId,
context: Context<T>,
new_window_handler: Option<Arc<tauri_runtime::webview::NewWindowHandler<T, crate::CefRuntime<T>>>>,
}
impl LifeSpanHandler {
@ -616,6 +617,81 @@ wrap_life_span_handler! {
on_window_destroyed(self.window_id, &self.context.windows, &self.context.callback);
}
}
fn on_before_popup(
&self,
_browser: Option<&mut Browser>,
_frame: Option<&mut Frame>,
_popup_id: std::os::raw::c_int,
target_url: Option<&CefString>,
_target_frame_name: Option<&CefString>,
_target_disposition: WindowOpenDisposition,
_user_gesture: std::os::raw::c_int,
popup_features: Option<&PopupFeatures>,
_window_info: Option<&mut WindowInfo>,
_client: Option<&mut Option<Client>>,
_settings: Option<&mut BrowserSettings>,
_extra_info: Option<&mut Option<DictionaryValue>>,
_no_javascript_access: Option<&mut i32>,
) -> std::os::raw::c_int {
let Some(handler) = &self.new_window_handler else {
// No handler, allow default behavior
return 0;
};
let Some(target_url) = target_url else {
// No URL, deny
return 1;
};
let url_str = target_url.to_string();
let Ok(url) = url::Url::parse(&url_str) else {
// Invalid URL, deny
return 1;
};
// Extract size and position from popup_features
// Note: PopupFeatures fields may vary by CEF version, so we handle them defensively
let size = popup_features.and_then(|_features| {
// Try to access width/height fields - structure may vary
// For now, we'll use None if we can't determine the size
None // TODO: Implement proper PopupFeatures field access when CEF API is available
});
let position = popup_features.and_then(|_features| {
// Try to access x/y fields - structure may vary
// For now, we'll use None if we can't determine the position
None // TODO: Implement proper PopupFeatures field access when CEF API is available
});
let features = tauri_runtime::webview::NewWindowFeatures::new(
size,
position,
crate::NewWindowOpener {},
);
let response = handler(url, features);
match response {
tauri_runtime::webview::NewWindowResponse::Allow => {
// Allow CEF to handle the popup with default behavior
0
}
tauri_runtime::webview::NewWindowResponse::Create { window_id: _window_id } => {
// We need to create a window and associate it with the popup
// For now, we'll deny the popup and let the handler create the window
// The window creation should happen via the message system
// This is a limitation - CEF doesn't easily support creating a window
// and associating it with a popup in the callback
// We return 1 to cancel the popup, and the handler should create the window
1
}
tauri_runtime::webview::NewWindowResponse::Deny => {
// Deny the popup
1
}
}
}
}
}
@ -627,6 +703,7 @@ wrap_client! {
on_page_load_handler: Option<Arc<tauri_runtime::webview::OnPageLoadHandler>>,
document_title_changed_handler: Option<Arc<tauri_runtime::webview::DocumentTitleChangedHandler>>,
navigation_handler: Option<Arc<tauri_runtime::webview::NavigationHandler>>,
new_window_handler: Option<Arc<tauri_runtime::webview::NewWindowHandler<T, crate::CefRuntime<T>>>>,
download_handler: Option<Arc<tauri_runtime::webview::DownloadHandler>>,
devtools_enabled: bool,
custom_scheme_domain_names: Vec<String>,
@ -643,7 +720,12 @@ wrap_client! {
}
fn life_span_handler(&self) -> Option<LifeSpanHandler> {
Some(BrowserLifeSpanHandler::new(self.window_kind, self.window_id, self.context.clone()))
Some(BrowserLifeSpanHandler::new(
self.window_kind,
self.window_id,
self.context.clone(),
self.new_window_handler.clone(),
))
}
fn load_handler(&self) -> Option<LoadHandler> {
@ -2459,12 +2541,13 @@ fn create_browser_window<T: UserEvent>(
) {
let PendingWebview {
label: webview_label,
opener: _,
mut webview_attributes,
platform_specific_attributes: _,
uri_scheme_protocols,
ipc_handler: _,
navigation_handler,
new_window_handler: _,
new_window_handler,
document_title_changed_handler,
url,
web_resource_request_handler: _,
@ -2481,6 +2564,7 @@ fn create_browser_window<T: UserEvent>(
let on_page_load_handler = on_page_load_handler.take().map(Arc::from);
let document_title_changed_handler = document_title_changed_handler.map(Arc::from);
let navigation_handler = navigation_handler.map(Arc::from);
let new_window_handler = new_window_handler.map(Arc::from);
let devtools_enabled = (cfg!(debug_assertions) || cfg!(feature = "devtools"))
&& webview_attributes.devtools.unwrap_or(true);
@ -2528,6 +2612,7 @@ fn create_browser_window<T: UserEvent>(
on_page_load_handler,
document_title_changed_handler,
navigation_handler,
new_window_handler,
download_handler,
devtools_enabled,
custom_scheme_domain_names.clone(),
@ -2795,12 +2880,13 @@ pub(crate) fn create_webview<T: UserEvent>(
) {
let PendingWebview {
label,
opener: _,
mut webview_attributes,
platform_specific_attributes,
uri_scheme_protocols,
ipc_handler: _,
navigation_handler,
new_window_handler: _,
new_window_handler,
document_title_changed_handler,
url,
web_resource_request_handler: _,
@ -2830,6 +2916,7 @@ pub(crate) fn create_webview<T: UserEvent>(
let on_page_load_handler = on_page_load_handler.take().map(Arc::from);
let document_title_changed_handler = document_title_changed_handler.map(Arc::from);
let navigation_handler = navigation_handler.map(Arc::from);
let new_window_handler = new_window_handler.map(Arc::from);
let devtools_enabled = (cfg!(debug_assertions) || cfg!(feature = "devtools"))
&& webview_attributes.devtools.unwrap_or(true);
@ -2853,6 +2940,7 @@ pub(crate) fn create_webview<T: UserEvent>(
on_page_load_handler,
document_title_changed_handler,
navigation_handler,
new_window_handler,
download_handler,
devtools_enabled,
custom_scheme_domain_names.clone(),

View File

@ -2017,6 +2017,9 @@ pub enum RuntimeStyle {
Chrome,
}
#[derive(Debug)]
pub struct NewWindowOpener {}
impl<T: UserEvent> Runtime<T> for CefRuntime<T> {
type WindowDispatcher = CefWindowDispatcher<T>;
type WebviewDispatcher = CefWebviewDispatcher<T>;
@ -2024,6 +2027,7 @@ impl<T: UserEvent> Runtime<T> for CefRuntime<T> {
type EventLoopProxy = EventProxy<T>;
type PlatformSpecificWebviewAttribute = WebviewAtribute;
type PlatformSpecificInitAttribute = RuntimeInitAttribute;
type WindowOpener = NewWindowOpener;
fn new(args: RuntimeInitArgs<RuntimeInitAttribute>) -> Result<Self> {
Ok(Self::init(args))

View File

@ -163,6 +163,69 @@ mod window;
pub use webview::Webview;
use window::WindowExt as _;
/// Information about the webview that initiated a new window request.
#[derive(Debug)]
pub struct NewWindowOpener {
/// The instance of the webview that initiated the new window request.
///
/// This must be set as the related view of the new webview.
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
pub webview: webkit2gtk::WebView,
/// The instance of the webview that initiated the new window request.
///
/// The target webview environment **MUST** match the environment of the opener webview.
#[cfg(windows)]
pub webview: webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2,
#[cfg(windows)]
pub environment: webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Environment,
/// The instance of the webview that initiated the new window request.
#[cfg(target_os = "macos")]
pub webview: objc2::rc::Retained<objc2_web_kit::WKWebView>,
/// Configuration of the target webview.
///
/// This **MUST** be used when creating the target webview.
#[cfg(target_os = "macos")]
pub target_configuration: objc2::rc::Retained<objc2_web_kit::WKWebViewConfiguration>,
}
// opener is only used on the main thread
unsafe impl Send for NewWindowOpener {}
unsafe impl Sync for NewWindowOpener {}
/// Platform-specific webview attributes.
pub enum WebviewAttribute {
/// Set the environment for the webview.
/// Useful if you need to share the same environment, for instance when using the [`PendingWebview::new_window_handler`].
#[cfg(windows)]
Environment(webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Environment),
/// Creates a new webview sharing the same web process with the provided webview.
/// Useful if you need to link a webview to another, for instance when using the [`PendingWebview::new_window_handler`].
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
RelatedView(webkit2gtk::WebView),
/// Set the webview configuration.
/// Useful if you need to share the use a predefined webview configuration, for instance when using the [`PendingWebview::new_window_handler`].
#[cfg(target_os = "macos")]
WebviewConfiguration(objc2::rc::Retained<objc2_web_kit::WKWebViewConfiguration>),
}
// attribute is only used on the main thread
unsafe impl Send for WebviewAttribute {}
unsafe impl Sync for WebviewAttribute {}
#[derive(Debug)]
pub struct WebContext {
pub inner: WryWebContext,
@ -2850,8 +2913,9 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
type Handle = WryHandle<T>;
type EventLoopProxy = EventProxy<T>;
type PlatformSpecificWebviewAttribute = ();
type PlatformSpecificWebviewAttribute = WebviewAttribute;
type PlatformSpecificInitAttribute = ();
type WindowOpener = NewWindowOpener;
fn new(args: RuntimeInitArgs<()>) -> Result<Self> {
Self::init_with_builder(EventLoopBuilder::<Message<T>>::with_user_event(), args)
@ -4620,10 +4684,12 @@ You may have it installed on another user account, but it is not available for t
#[allow(unused_mut)]
let PendingWebview {
webview_attributes,
platform_specific_attributes,
uri_scheme_protocols,
label,
ipc_handler,
url,
opener,
..
} = pending;
@ -4672,7 +4738,15 @@ You may have it installed on another user account, but it is not available for t
}
#[cfg(target_os = "macos")]
if let Some(webview_configuration) = webview_attributes.webview_configuration {
if let Some(webview_configuration) = platform_specific_attributes
.iter()
.find_map(|attr| match attr {
WebviewAttribute::WebviewConfiguration(config) => Some(config),
#[allow(unreachable_patterns)]
_ => None,
})
.or_else(|| opener.as_ref().map(|opener| &opener.target_configuration))
{
webview_builder = webview_builder.with_webview_configuration(webview_configuration);
}
@ -4761,7 +4835,7 @@ You may have it installed on another user account, but it is not available for t
tauri_runtime::webview::NewWindowFeatures::new(
features.size,
features.position,
tauri_runtime::webview::NewWindowOpener {
NewWindowOpener {
#[cfg(desktop)]
webview: features.opener.webview,
#[cfg(windows)]
@ -4907,8 +4981,16 @@ You may have it installed on another user account, but it is not available for t
webview_builder = webview_builder.with_additional_browser_args(&additional_browser_args);
}
if let Some(environment) = webview_attributes.environment {
webview_builder = webview_builder.with_environment(environment);
if let Some(environment) = platform_specific_attributes
.iter()
.find_map(|attr| match attr {
WebviewAttribute::Environment(env) => Some(env),
#[allow(unreachable_patterns)]
_ => None,
})
.or_else(|| opener.as_ref().map(|opener| &opener.environment))
{
webview_builder = webview_builder.with_environment(environment.clone());
}
webview_builder = webview_builder.with_theme(match window.theme() {
@ -4953,8 +5035,16 @@ You may have it installed on another user account, but it is not available for t
target_os = "openbsd"
))]
{
if let Some(related_view) = webview_attributes.related_view {
webview_builder = webview_builder.with_related_view(related_view);
if let Some(related_view) = platform_specific_attributes
.iter()
.find_map(|attr| match attr {
WebviewAttribute::RelatedView(view) => Some(view),
#[allow(unreachable_patterns)]
_ => None,
})
.or_else(|| opener.as_ref().map(|opener| &opener.webview))
{
webview_builder = webview_builder.with_related_view(related_view.clone());
}
}

View File

@ -411,6 +411,8 @@ pub trait Runtime<T: UserEvent>: Debug + Sized + 'static {
type PlatformSpecificWebviewAttribute: Send + Sync + 'static;
/// The platform specific runtime init arguments.
type PlatformSpecificInitAttribute: Send + Sync + 'static;
/// Data about the window that requested the new window for [`PendingWebview::new_window_handler`].
type WindowOpener: Send + Sync + Debug;
/// Creates a new webview runtime. Must be used on the main thread.
fn new(args: RuntimeInitArgs<Self::PlatformSpecificInitAttribute>) -> Result<Self>;

View File

@ -33,7 +33,8 @@ pub type WebResourceRequestHandler =
pub type NavigationHandler = dyn Fn(&Url) -> bool + Send;
pub type NewWindowHandler = dyn Fn(Url, NewWindowFeatures) -> NewWindowResponse + Send + Sync;
pub type NewWindowHandler<T, R> =
dyn Fn(Url, NewWindowFeatures<T, R>) -> NewWindowResponse + Send + Sync;
pub type OnPageLoadHandler = dyn Fn(Url, PageLoadEvent) + Send;
@ -85,50 +86,19 @@ pub enum PageLoadEvent {
Finished,
}
/// Information about the webview that initiated a new window request.
#[derive(Debug)]
pub struct NewWindowOpener {
/// The instance of the webview that initiated the new window request.
///
/// This must be set as the related view of the new webview. See [`WebviewAttributes::related_view`].
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
pub webview: webkit2gtk::WebView,
/// The instance of the webview that initiated the new window request.
///
/// The target webview environment **MUST** match the environment of the opener webview. See [`WebviewAttributes::environment`].
#[cfg(windows)]
pub webview: webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2,
#[cfg(windows)]
pub environment: webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Environment,
/// The instance of the webview that initiated the new window request.
#[cfg(target_os = "macos")]
pub webview: objc2::rc::Retained<objc2_web_kit::WKWebView>,
/// Configuration of the target webview.
///
/// This **MUST** be used when creating the target webview. See [`WebviewAttributes::webview_configuration`].
#[cfg(target_os = "macos")]
pub target_configuration: objc2::rc::Retained<objc2_web_kit::WKWebViewConfiguration>,
}
/// Window features of a window requested to open.
#[derive(Debug)]
pub struct NewWindowFeatures {
pub struct NewWindowFeatures<T: UserEvent, R: Runtime<T>> {
pub(crate) size: Option<crate::dpi::LogicalSize<f64>>,
pub(crate) position: Option<crate::dpi::LogicalPosition<f64>>,
pub(crate) opener: NewWindowOpener,
pub(crate) opener: R::WindowOpener,
}
impl NewWindowFeatures {
impl<T: UserEvent, R: Runtime<T>> NewWindowFeatures<T, R> {
pub fn new(
size: Option<crate::dpi::LogicalSize<f64>>,
position: Option<crate::dpi::LogicalPosition<f64>>,
opener: NewWindowOpener,
opener: R::WindowOpener,
) -> Self {
Self {
size,
@ -150,9 +120,14 @@ impl NewWindowFeatures {
}
/// Returns information about the webview that initiated a new window request.
pub fn opener(&self) -> &NewWindowOpener {
pub fn opener(&self) -> &R::WindowOpener {
&self.opener
}
/// Returns information about the webview that initiated a new window request.
pub fn into_opener(self) -> R::WindowOpener {
self.opener
}
}
/// Response for the new window request handler.
@ -161,10 +136,7 @@ pub enum NewWindowResponse {
Allow,
/// Allow the window to be opened, with the given window.
///
/// ## Platform-specific:
///
/// **Linux**: The webview must be related to the caller webview. See [`WebviewAttributes::related_view`].
/// **Windows**: The webview must use the same environment as the caller webview. See [`WebviewAttributes::environment`].
/// The window must be created referencing the opener window so it can inherit the appropriate attributes.
#[cfg(not(any(target_os = "android", target_os = "ios")))]
Create { window_id: WindowId },
/// Deny the window from being opened.
@ -199,6 +171,9 @@ pub struct PendingWebview<T: UserEvent, R: Runtime<T>> {
/// The [`WebviewAttributes`] that the webview will be created with.
pub webview_attributes: WebviewAttributes,
/// Information about the webview that initiated a new window request.
pub opener: Option<R::WindowOpener>,
/// Runtime specific attributes.
pub platform_specific_attributes: Vec<R::PlatformSpecificWebviewAttribute>,
@ -211,7 +186,7 @@ pub struct PendingWebview<T: UserEvent, R: Runtime<T>> {
/// A handler to decide if incoming url is allowed to navigate.
pub navigation_handler: Option<Box<NavigationHandler>>,
pub new_window_handler: Option<Box<NewWindowHandler>>,
pub new_window_handler: Option<Box<NewWindowHandler<T, R>>>,
pub document_title_changed_handler: Option<Box<DocumentTitleChangedHandler>>,
@ -243,6 +218,7 @@ impl<T: UserEvent, R: Runtime<T>> PendingWebview<T, R> {
} else {
Ok(Self {
webview_attributes,
opener: None,
platform_specific_attributes,
uri_scheme_protocols: Default::default(),
label,
@ -381,25 +357,6 @@ pub struct WebviewAttributes {
/// This relies on [`objc2_ui_kit`] which does not provide a stable API yet, so it can receive breaking changes in minor releases.
#[cfg(target_os = "ios")]
pub input_accessory_view_builder: Option<InputAccessoryViewBuilder>,
/// Set the environment for the webview.
/// Useful if you need to share the same environment, for instance when using the [`PendingWebview::new_window_handler`].
#[cfg(windows)]
pub environment: Option<webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Environment>,
/// Creates a new webview sharing the same web process with the provided webview.
/// Useful if you need to link a webview to another, for instance when using the [`PendingWebview::new_window_handler`].
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
pub related_view: Option<webkit2gtk::WebView>,
#[cfg(target_os = "macos")]
pub webview_configuration: Option<objc2::rc::Retained<objc2_web_kit::WKWebViewConfiguration>>,
}
unsafe impl Send for WebviewAttributes {}
@ -515,18 +472,6 @@ impl WebviewAttributes {
scroll_bar_style: ScrollBarStyle::Default,
#[cfg(target_os = "ios")]
input_accessory_view_builder: None,
#[cfg(windows)]
environment: None,
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
related_view: None,
#[cfg(target_os = "macos")]
webview_configuration: None,
}
}

View File

@ -18,6 +18,12 @@ pub use cookie;
use http::HeaderMap;
use serde::Serialize;
use tauri_macros::default_runtime;
#[cfg(feature = "cef")]
pub use tauri_runtime_cef::NewWindowOpener as CefWindowOpener;
#[cfg(feature = "wry")]
pub use tauri_runtime_wry::NewWindowOpener as WryWindowOpener;
pub use tauri_runtime::webview::{NewWindowFeatures, PageLoadEvent, ScrollBarStyle};
// Remove this re-export in v3
pub use tauri_runtime::Cookie;
@ -58,8 +64,9 @@ use std::{
pub(crate) type WebResourceRequestHandler =
dyn Fn(http::Request<Vec<u8>>, &mut http::Response<Cow<'static, [u8]>>) + Send + Sync;
pub(crate) type NavigationHandler = dyn Fn(&Url) -> bool + Send;
pub(crate) type NewWindowHandler<R> =
dyn Fn(Url, NewWindowFeatures) -> NewWindowResponse<R> + Send + Sync;
pub(crate) type NewWindowHandler<R> = dyn Fn(Url, tauri_runtime::webview::NewWindowFeatures<EventLoopMessage, R>) -> NewWindowResponse<R>
+ Send
+ Sync;
pub(crate) type UriSchemeProtocolHandler =
Box<dyn Fn(&str, http::Request<Vec<u8>>, UriSchemeResponder) + Send + Sync>;
pub(crate) type OnPageLoad<R> = dyn Fn(Webview<R>, PageLoadPayload<'_>) + Send + Sync + 'static;
@ -272,6 +279,7 @@ unstable_struct!(
struct WebviewBuilder<R: Runtime> {
pub(crate) label: String,
pub(crate) webview_attributes: WebviewAttributes,
pub(crate) opener: Option<R::WindowOpener>,
pub(crate) platform_specific_attributes: Vec<R::PlatformSpecificWebviewAttribute>,
pub(crate) web_resource_request_handler: Option<Box<WebResourceRequestHandler>>,
pub(crate) navigation_handler: Option<Box<NavigationHandler>>,
@ -365,6 +373,7 @@ async fn create_window(app: tauri::AppHandle) {
Self {
label: label.into(),
webview_attributes: WebviewAttributes::new(url),
opener: None,
platform_specific_attributes: Vec::new(),
web_resource_request_handler: None,
navigation_handler: None,
@ -445,6 +454,7 @@ async fn create_window(app: tauri::AppHandle) {
Self {
label: config.label.clone(),
webview_attributes: WebviewAttributes::from(&config),
opener: None,
platform_specific_attributes: Vec::new(),
web_resource_request_handler: None,
navigation_handler: None,
@ -602,7 +612,13 @@ tauri::Builder::default()
///
/// [window.open]: https://developer.mozilla.org/en-US/docs/Web/API/Window/open
pub fn on_new_window<
F: Fn(Url, NewWindowFeatures) -> NewWindowResponse<R> + Send + Sync + 'static,
F: Fn(
Url,
tauri_runtime::webview::NewWindowFeatures<EventLoopMessage, R>,
) -> NewWindowResponse<R>
+ Send
+ Sync
+ 'static,
>(
mut self,
f: F,
@ -714,6 +730,11 @@ tauri::Builder::default()
self
}
pub fn opener(mut self, opener: R::WindowOpener) -> Self {
self.opener.replace(opener);
self
}
pub(crate) fn into_pending_webview<M: Manager<R>>(
mut self,
manager: &M,
@ -724,26 +745,32 @@ tauri::Builder::default()
self.platform_specific_attributes,
self.label.clone(),
)?;
pending.opener = self.opener.take();
pending.navigation_handler = self.navigation_handler.take();
pending.new_window_handler = self.new_window_handler.take().map(|handler| {
Box::new(
move |url, features: NewWindowFeatures| match handler(url, features) {
NewWindowResponse::Allow => tauri_runtime::webview::NewWindowResponse::Allow,
#[cfg(mobile)]
NewWindowResponse::Create { window: _ } => {
tauri_runtime::webview::NewWindowResponse::Allow
}
#[cfg(desktop)]
NewWindowResponse::Create { window } => {
tauri_runtime::webview::NewWindowResponse::Create {
window_id: window.window.window.id,
move |url, features: tauri_runtime::webview::NewWindowFeatures<EventLoopMessage, R>| {
match handler(url, features) {
NewWindowResponse::Allow => tauri_runtime::webview::NewWindowResponse::Allow,
#[cfg(mobile)]
NewWindowResponse::Create { window: _ } => {
tauri_runtime::webview::NewWindowResponse::Allow
}
#[cfg(desktop)]
NewWindowResponse::Create { window } => {
tauri_runtime::webview::NewWindowResponse::Create {
window_id: window.window.window.id,
}
}
NewWindowResponse::Deny => tauri_runtime::webview::NewWindowResponse::Deny,
}
NewWindowResponse::Deny => tauri_runtime::webview::NewWindowResponse::Deny,
},
)
as Box<
dyn Fn(Url, NewWindowFeatures) -> tauri_runtime::webview::NewWindowResponse
dyn Fn(
Url,
tauri_runtime::webview::NewWindowFeatures<EventLoopMessage, R>,
) -> tauri_runtime::webview::NewWindowResponse
+ Send
+ Sync
+ 'static,
@ -1252,32 +1279,41 @@ fn main() {
));
self
}
}
/// Wry APIs
#[cfg(feature = "wry")]
impl WebviewBuilder<crate::Wry> {
/// Set the environment for the webview.
/// Useful if you need to share the same environment, for instance when using the [`Self::on_new_window`].
#[cfg(all(feature = "wry", windows))]
#[cfg(windows)]
pub fn with_environment(
mut self,
environment: webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Environment,
) -> Self {
self.webview_attributes.environment.replace(environment);
self
.platform_specific_attributes
.push(tauri_runtime_wry::WebviewAttribute::Environment(
environment,
));
self
}
/// Creates a new webview sharing the same web process with the provided webview.
/// Useful if you need to link a webview to another, for instance when using the [`Self::on_new_window`].
#[cfg(all(
feature = "wry",
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
)
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
pub fn with_related_view(mut self, related_view: webkit2gtk::WebView) -> Self {
self.webview_attributes.related_view.replace(related_view);
self
.platform_specific_attributes
.push(tauri_runtime_wry::WebviewAttribute::RelatedView(
related_view,
));
self
}
@ -1288,10 +1324,9 @@ fn main() {
mut self,
webview_configuration: objc2::rc::Retained<objc2_web_kit::WKWebViewConfiguration>,
) -> Self {
self
.webview_attributes
.webview_configuration
.replace(webview_configuration);
self.platform_specific_attributes.push(
tauri_runtime_wry::WebviewAttribute::WebviewConfiguration(webview_configuration),
);
self
}
}

View File

@ -339,7 +339,10 @@ impl<'a, R: Runtime, M: Manager<R>> WebviewWindowBuilder<'a, R, M> {
///
/// [window.open]: https://developer.mozilla.org/en-US/docs/Web/API/Window/open
pub fn on_new_window<
F: Fn(Url, NewWindowFeatures) -> NewWindowResponse<R> + Send + Sync + 'static,
F: Fn(Url, NewWindowFeatures<crate::EventLoopMessage, R>) -> NewWindowResponse<R>
+ Send
+ Sync
+ 'static,
>(
mut self,
f: F,
@ -1307,9 +1310,41 @@ impl<R: Runtime, M: Manager<R>> WebviewWindowBuilder<'_, R, M> {
self
}
/// Set the window features.
/// Useful if you need to share the same window features, for instance when using the [`Self::on_new_window`].
#[cfg(any(
target_os = "macos",
windows,
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
pub fn window_features(
mut self,
features: NewWindowFeatures<crate::EventLoopMessage, R>,
) -> Self {
if let Some(position) = features.position() {
self.window_builder = self.window_builder.position(position.x, position.y);
}
if let Some(size) = features.size() {
self.window_builder = self.window_builder.inner_size(size.width, size.height);
}
self.webview_builder = self.webview_builder.opener(features.into_opener());
self
}
}
/// Wry APIs
#[cfg(feature = "wry")]
impl<M: Manager<crate::Wry>> WebviewWindowBuilder<'_, crate::Wry, M> {
/// Set the environment for the webview.
/// Useful if you need to share the same environment, for instance when using the [`Self::on_new_window`].
#[cfg(all(feature = "wry", windows))]
#[cfg(windows)]
pub fn with_environment(
mut self,
environment: webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Environment,
@ -1320,15 +1355,12 @@ impl<R: Runtime, M: Manager<R>> WebviewWindowBuilder<'_, R, M> {
/// Creates a new webview sharing the same web process with the provided webview.
/// Useful if you need to link a webview to another, for instance when using the [`Self::on_new_window`].
#[cfg(all(
feature = "wry",
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
)
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
pub fn with_related_view(mut self, related_view: webkit2gtk::WebView) -> Self {
self.webview_builder = self.webview_builder.with_related_view(related_view);
@ -1347,58 +1379,6 @@ impl<R: Runtime, M: Manager<R>> WebviewWindowBuilder<'_, R, M> {
.with_webview_configuration(webview_configuration);
self
}
/// Set the window features.
/// Useful if you need to share the same window features, for instance when using the [`Self::on_new_window`].
#[cfg(any(
target_os = "macos",
windows,
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
pub fn window_features(mut self, features: NewWindowFeatures) -> Self {
if let Some(position) = features.position() {
self.window_builder = self.window_builder.position(position.x, position.y);
}
if let Some(size) = features.size() {
self.window_builder = self.window_builder.inner_size(size.width, size.height);
}
#[cfg(target_os = "macos")]
{
self.webview_builder = self
.webview_builder
.with_webview_configuration(features.opener().target_configuration.clone());
}
#[cfg(all(feature = "wry", windows))]
{
self.webview_builder = self
.webview_builder
.with_environment(features.opener().environment.clone());
}
#[cfg(all(
feature = "wry",
any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
)
))]
{
self.webview_builder = self
.webview_builder
.with_related_view(features.opener().webview.clone());
}
self
}
}
/// A type that wraps a [`Window`] together with a [`Webview`].