mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-09-11 16:08:21 +03:00
feat(webview): add reparent API (#8939)
* feat(webview): add reparent API * fix build * fix import * remove cfg * fix windows * clone * clone value * ()
This commit is contained in:
parent
b5eb64728a
commit
fdcaf935fa
8
.changes/reparent.md
Normal file
8
.changes/reparent.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
"@tauri-apps/api": patch:feat
|
||||||
|
"tauri": patch:feat
|
||||||
|
"tauri-runtime": patch:feat
|
||||||
|
"tauri-runtime-wry": patch:feat
|
||||||
|
---
|
||||||
|
|
||||||
|
Added the `reparent` function to the webview API.
|
@ -170,7 +170,11 @@ macro_rules! webview_getter {
|
|||||||
getter!(
|
getter!(
|
||||||
$self,
|
$self,
|
||||||
rx,
|
rx,
|
||||||
Message::Webview($self.window_id, $self.webview_id, $message(tx))
|
Message::Webview(
|
||||||
|
*$self.window_id.lock().unwrap(),
|
||||||
|
$self.webview_id,
|
||||||
|
$message(tx)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@ -280,7 +284,7 @@ impl<T: UserEvent> Context<T> {
|
|||||||
let detached_webview = webview_id.map(|id| DetachedWebview {
|
let detached_webview = webview_id.map(|id| DetachedWebview {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
dispatcher: WryWebviewDispatcher {
|
dispatcher: WryWebviewDispatcher {
|
||||||
window_id,
|
window_id: Arc::new(Mutex::new(window_id)),
|
||||||
webview_id: id,
|
webview_id: id,
|
||||||
context: self.clone(),
|
context: self.clone(),
|
||||||
},
|
},
|
||||||
@ -304,6 +308,9 @@ impl<T: UserEvent> Context<T> {
|
|||||||
|
|
||||||
let webview_id = self.next_webview_id();
|
let webview_id = self.next_webview_id();
|
||||||
|
|
||||||
|
let window_id_wrapper = Arc::new(Mutex::new(window_id));
|
||||||
|
let window_id_wrapper_ = window_id_wrapper.clone();
|
||||||
|
|
||||||
send_user_message(
|
send_user_message(
|
||||||
self,
|
self,
|
||||||
Message::CreateWebview(
|
Message::CreateWebview(
|
||||||
@ -312,7 +319,7 @@ impl<T: UserEvent> Context<T> {
|
|||||||
create_webview(
|
create_webview(
|
||||||
WebviewKind::WindowChild,
|
WebviewKind::WindowChild,
|
||||||
window,
|
window,
|
||||||
window_id,
|
window_id_wrapper_,
|
||||||
webview_id,
|
webview_id,
|
||||||
&context,
|
&context,
|
||||||
pending,
|
pending,
|
||||||
@ -322,7 +329,7 @@ impl<T: UserEvent> Context<T> {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let dispatcher = WryWebviewDispatcher {
|
let dispatcher = WryWebviewDispatcher {
|
||||||
window_id,
|
window_id: window_id_wrapper,
|
||||||
webview_id,
|
webview_id,
|
||||||
context: self.clone(),
|
context: self.clone(),
|
||||||
};
|
};
|
||||||
@ -1170,6 +1177,7 @@ pub enum WebviewMessage {
|
|||||||
SetPosition(Position),
|
SetPosition(Position),
|
||||||
SetSize(Size),
|
SetSize(Size),
|
||||||
SetFocus,
|
SetFocus,
|
||||||
|
Reparent(WindowId),
|
||||||
// Getters
|
// Getters
|
||||||
Url(Sender<Url>),
|
Url(Sender<Url>),
|
||||||
Position(Sender<PhysicalPosition<i32>>),
|
Position(Sender<PhysicalPosition<i32>>),
|
||||||
@ -1220,7 +1228,7 @@ impl<T: UserEvent> Clone for Message<T> {
|
|||||||
/// The Tauri [`WebviewDispatch`] for [`Wry`].
|
/// The Tauri [`WebviewDispatch`] for [`Wry`].
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct WryWebviewDispatcher<T: UserEvent> {
|
pub struct WryWebviewDispatcher<T: UserEvent> {
|
||||||
window_id: WindowId,
|
window_id: Arc<Mutex<WindowId>>,
|
||||||
webview_id: WebviewId,
|
webview_id: WebviewId,
|
||||||
context: Context<T>,
|
context: Context<T>,
|
||||||
}
|
}
|
||||||
@ -1235,7 +1243,7 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
fn on_webview_event<F: Fn(&WebviewEvent) + Send + 'static>(&self, f: F) -> WindowEventId {
|
fn on_webview_event<F: Fn(&WebviewEvent) + Send + 'static>(&self, f: F) -> WindowEventId {
|
||||||
let id = self.context.next_webview_event_id();
|
let id = self.context.next_webview_event_id();
|
||||||
let _ = self.context.proxy.send_event(Message::Webview(
|
let _ = self.context.proxy.send_event(Message::Webview(
|
||||||
self.window_id,
|
*self.window_id.lock().unwrap(),
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::AddEventListener(id, Box::new(f)),
|
WebviewMessage::AddEventListener(id, Box::new(f)),
|
||||||
));
|
));
|
||||||
@ -1246,7 +1254,7 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(
|
Message::Webview(
|
||||||
self.window_id,
|
*self.window_id.lock().unwrap(),
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::WithWebview(Box::new(move |webview| f(Box::new(webview)))),
|
WebviewMessage::WithWebview(Box::new(move |webview| f(Box::new(webview)))),
|
||||||
),
|
),
|
||||||
@ -1258,7 +1266,7 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
let _ = send_user_message(
|
let _ = send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(
|
Message::Webview(
|
||||||
self.window_id,
|
*self.window_id.lock().unwrap(),
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::OpenDevTools,
|
WebviewMessage::OpenDevTools,
|
||||||
),
|
),
|
||||||
@ -1270,7 +1278,7 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
let _ = send_user_message(
|
let _ = send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(
|
Message::Webview(
|
||||||
self.window_id,
|
*self.window_id.lock().unwrap(),
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::CloseDevTools,
|
WebviewMessage::CloseDevTools,
|
||||||
),
|
),
|
||||||
@ -1303,7 +1311,7 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(
|
Message::Webview(
|
||||||
self.window_id,
|
*self.window_id.lock().unwrap(),
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::Navigate(url),
|
WebviewMessage::Navigate(url),
|
||||||
),
|
),
|
||||||
@ -1313,14 +1321,22 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
fn print(&self) -> Result<()> {
|
fn print(&self) -> Result<()> {
|
||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(self.window_id, self.webview_id, WebviewMessage::Print),
|
Message::Webview(
|
||||||
|
*self.window_id.lock().unwrap(),
|
||||||
|
self.webview_id,
|
||||||
|
WebviewMessage::Print,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(&self) -> Result<()> {
|
fn close(&self) -> Result<()> {
|
||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(self.window_id, self.webview_id, WebviewMessage::Close),
|
Message::Webview(
|
||||||
|
*self.window_id.lock().unwrap(),
|
||||||
|
self.webview_id,
|
||||||
|
WebviewMessage::Close,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1328,7 +1344,7 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(
|
Message::Webview(
|
||||||
self.window_id,
|
*self.window_id.lock().unwrap(),
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::SetSize(size),
|
WebviewMessage::SetSize(size),
|
||||||
),
|
),
|
||||||
@ -1339,7 +1355,7 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(
|
Message::Webview(
|
||||||
self.window_id,
|
*self.window_id.lock().unwrap(),
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::SetPosition(position),
|
WebviewMessage::SetPosition(position),
|
||||||
),
|
),
|
||||||
@ -1349,10 +1365,29 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
fn set_focus(&self) -> Result<()> {
|
fn set_focus(&self) -> Result<()> {
|
||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(self.window_id, self.webview_id, WebviewMessage::SetFocus),
|
Message::Webview(
|
||||||
|
*self.window_id.lock().unwrap(),
|
||||||
|
self.webview_id,
|
||||||
|
WebviewMessage::SetFocus,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reparent(&self, window_id: WindowId) -> Result<()> {
|
||||||
|
let mut current_window_id = self.window_id.lock().unwrap();
|
||||||
|
send_user_message(
|
||||||
|
&self.context,
|
||||||
|
Message::Webview(
|
||||||
|
*current_window_id,
|
||||||
|
self.webview_id,
|
||||||
|
WebviewMessage::Reparent(window_id),
|
||||||
|
),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
*current_window_id = window_id;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "tracing", not(target_os = "android")))]
|
#[cfg(all(feature = "tracing", not(target_os = "android")))]
|
||||||
fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
|
fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
|
||||||
// use a channel so the EvaluateScript task uses the current span as parent
|
// use a channel so the EvaluateScript task uses the current span as parent
|
||||||
@ -1361,7 +1396,7 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
self,
|
self,
|
||||||
rx,
|
rx,
|
||||||
Message::Webview(
|
Message::Webview(
|
||||||
self.window_id,
|
*self.window_id.lock().unwrap(),
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::EvaluateScript(script.into(), tx, tracing::Span::current()),
|
WebviewMessage::EvaluateScript(script.into(), tx, tracing::Span::current()),
|
||||||
)
|
)
|
||||||
@ -1373,7 +1408,7 @@ impl<T: UserEvent> WebviewDispatch<T> for WryWebviewDispatcher<T> {
|
|||||||
send_user_message(
|
send_user_message(
|
||||||
&self.context,
|
&self.context,
|
||||||
Message::Webview(
|
Message::Webview(
|
||||||
self.window_id,
|
*self.window_id.lock().unwrap(),
|
||||||
self.webview_id,
|
self.webview_id,
|
||||||
WebviewMessage::EvaluateScript(script.into()),
|
WebviewMessage::EvaluateScript(script.into()),
|
||||||
),
|
),
|
||||||
@ -2235,7 +2270,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
|||||||
let detached_webview = webview_id.map(|id| DetachedWebview {
|
let detached_webview = webview_id.map(|id| DetachedWebview {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
dispatcher: WryWebviewDispatcher {
|
dispatcher: WryWebviewDispatcher {
|
||||||
window_id,
|
window_id: Arc::new(Mutex::new(window_id)),
|
||||||
webview_id: id,
|
webview_id: id,
|
||||||
context: self.context.clone(),
|
context: self.context.clone(),
|
||||||
},
|
},
|
||||||
@ -2265,12 +2300,14 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
|||||||
.get(&window_id)
|
.get(&window_id)
|
||||||
.and_then(|w| w.inner.clone());
|
.and_then(|w| w.inner.clone());
|
||||||
if let Some(window) = window {
|
if let Some(window) = window {
|
||||||
|
let window_id_wrapper = Arc::new(Mutex::new(window_id));
|
||||||
|
|
||||||
let webview_id = self.context.next_webview_id();
|
let webview_id = self.context.next_webview_id();
|
||||||
|
|
||||||
let webview = create_webview(
|
let webview = create_webview(
|
||||||
WebviewKind::WindowChild,
|
WebviewKind::WindowChild,
|
||||||
&window,
|
&window,
|
||||||
window_id,
|
window_id_wrapper.clone(),
|
||||||
webview_id,
|
webview_id,
|
||||||
&self.context,
|
&self.context,
|
||||||
pending,
|
pending,
|
||||||
@ -2290,7 +2327,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let dispatcher = WryWebviewDispatcher {
|
let dispatcher = WryWebviewDispatcher {
|
||||||
window_id,
|
window_id: window_id_wrapper,
|
||||||
webview_id,
|
webview_id,
|
||||||
context: self.context.clone(),
|
context: self.context.clone(),
|
||||||
};
|
};
|
||||||
@ -2685,87 +2722,33 @@ fn handle_user_message<T: UserEvent>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Message::Webview(window_id, webview_id, webview_message) => {
|
Message::Webview(window_id, webview_id, webview_message) => {
|
||||||
let webview_handle = windows.0.borrow().get(&window_id).map(|w| {
|
if let WebviewMessage::Reparent(new_parent_window_id) = webview_message {
|
||||||
(
|
let webview_handle = windows.0.borrow_mut().get_mut(&window_id).and_then(|w| {
|
||||||
w.inner.clone(),
|
w.webviews
|
||||||
w.webviews.iter().find(|w| w.id == webview_id).cloned(),
|
.iter()
|
||||||
)
|
.position(|w| w.id == webview_id)
|
||||||
});
|
.map(|webview_index| w.webviews.remove(webview_index))
|
||||||
if let Some((Some(window), Some(webview))) = webview_handle {
|
});
|
||||||
match webview_message {
|
|
||||||
WebviewMessage::WebviewEvent(_) => { /* already handled */ }
|
|
||||||
WebviewMessage::SynthesizedWindowEvent(_) => { /* already handled */ }
|
|
||||||
|
|
||||||
WebviewMessage::AddEventListener(id, listener) => {
|
if let Some(webview) = webview_handle {
|
||||||
webview
|
if let Some((Some(new_parent_window), new_parent_window_webviews)) = windows
|
||||||
.webview_event_listeners
|
.0
|
||||||
.lock()
|
.borrow_mut()
|
||||||
.unwrap()
|
.get_mut(&new_parent_window_id)
|
||||||
.insert(id, listener);
|
.map(|w| (w.inner.clone(), &mut w.webviews))
|
||||||
}
|
{
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
#[cfg(all(feature = "tracing", not(target_os = "android")))]
|
{
|
||||||
WebviewMessage::EvaluateScript(script, tx, span) => {
|
use wry::WebViewExtMacOS;
|
||||||
let _span = span.entered();
|
webview.inner.reparent(new_parent_window.ns_window() as _);
|
||||||
if let Err(e) = webview.evaluate_script(&script) {
|
new_parent_window_webviews.push(webview);
|
||||||
debug_eprintln!("{}", e);
|
|
||||||
}
|
}
|
||||||
tx.send(()).unwrap();
|
#[cfg(windows)]
|
||||||
}
|
{
|
||||||
#[cfg(not(all(feature = "tracing", not(target_os = "android"))))]
|
webview.inner.reparent(new_parent_window.hwnd());
|
||||||
WebviewMessage::EvaluateScript(script) => {
|
new_parent_window_webviews.push(webview);
|
||||||
if let Err(e) = webview.evaluate_script(&script) {
|
|
||||||
debug_eprintln!("{}", e);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
WebviewMessage::Navigate(url) => webview.load_url(url.as_str()),
|
|
||||||
WebviewMessage::Print => {
|
|
||||||
let _ = webview.print();
|
|
||||||
}
|
|
||||||
WebviewMessage::Close => {
|
|
||||||
windows.0.borrow_mut().get_mut(&window_id).map(|window| {
|
|
||||||
if let Some(i) = window.webviews.iter().position(|w| w.id == webview.id) {
|
|
||||||
window.webviews.remove(i);
|
|
||||||
}
|
|
||||||
window
|
|
||||||
});
|
|
||||||
}
|
|
||||||
WebviewMessage::SetSize(size) => {
|
|
||||||
let mut bounds = webview.bounds();
|
|
||||||
let size = size.to_logical(window.scale_factor());
|
|
||||||
bounds.width = size.width;
|
|
||||||
bounds.height = size.height;
|
|
||||||
|
|
||||||
if let Some(b) = &webview.bounds {
|
|
||||||
let window_size = window.inner_size();
|
|
||||||
let mut bounds = b.lock().unwrap();
|
|
||||||
bounds.width_rate = size.width as f32 / window_size.width as f32;
|
|
||||||
bounds.height_rate = size.height as f32 / window_size.height as f32;
|
|
||||||
}
|
|
||||||
|
|
||||||
webview.set_bounds(bounds);
|
|
||||||
}
|
|
||||||
WebviewMessage::SetPosition(position) => {
|
|
||||||
let mut bounds = webview.bounds();
|
|
||||||
let position = position.to_logical(window.scale_factor());
|
|
||||||
bounds.x = position.x;
|
|
||||||
bounds.y = position.y;
|
|
||||||
|
|
||||||
if let Some(b) = &webview.bounds {
|
|
||||||
let window_size = window.inner_size();
|
|
||||||
let mut bounds = b.lock().unwrap();
|
|
||||||
bounds.width_rate = position.x as f32 / window_size.width as f32;
|
|
||||||
bounds.height_rate = position.y as f32 / window_size.height as f32;
|
|
||||||
}
|
|
||||||
|
|
||||||
webview.set_bounds(bounds);
|
|
||||||
}
|
|
||||||
WebviewMessage::SetFocus => {
|
|
||||||
webview.focus();
|
|
||||||
}
|
|
||||||
WebviewMessage::WithWebview(f) => {
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
target_os = "linux",
|
target_os = "linux",
|
||||||
target_os = "dragonfly",
|
target_os = "dragonfly",
|
||||||
@ -2774,68 +2757,163 @@ fn handle_user_message<T: UserEvent>(
|
|||||||
target_os = "openbsd"
|
target_os = "openbsd"
|
||||||
))]
|
))]
|
||||||
{
|
{
|
||||||
f(webview.webview());
|
if let Some(container) = new_parent_window.default_vbox() {
|
||||||
|
webview.inner.reparent(container);
|
||||||
|
new_parent_window_webviews.push(webview);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "macos")]
|
}
|
||||||
{
|
}
|
||||||
use wry::WebViewExtMacOS;
|
} else {
|
||||||
f(Webview {
|
let webview_handle = windows.0.borrow().get(&window_id).map(|w| {
|
||||||
webview: webview.webview(),
|
(
|
||||||
manager: webview.manager(),
|
w.inner.clone(),
|
||||||
ns_window: webview.ns_window(),
|
w.webviews.iter().find(|w| w.id == webview_id).cloned(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
if let Some((Some(window), Some(webview))) = webview_handle {
|
||||||
|
match webview_message {
|
||||||
|
WebviewMessage::WebviewEvent(_) => { /* already handled */ }
|
||||||
|
WebviewMessage::SynthesizedWindowEvent(_) => { /* already handled */ }
|
||||||
|
WebviewMessage::Reparent(_window_id) => { /* already handled */ }
|
||||||
|
WebviewMessage::AddEventListener(id, listener) => {
|
||||||
|
webview
|
||||||
|
.webview_event_listeners
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.insert(id, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "tracing", not(target_os = "android")))]
|
||||||
|
WebviewMessage::EvaluateScript(script, tx, span) => {
|
||||||
|
let _span = span.entered();
|
||||||
|
if let Err(e) = webview.evaluate_script(&script) {
|
||||||
|
debug_eprintln!("{}", e);
|
||||||
|
}
|
||||||
|
tx.send(()).unwrap();
|
||||||
|
}
|
||||||
|
#[cfg(not(all(feature = "tracing", not(target_os = "android"))))]
|
||||||
|
WebviewMessage::EvaluateScript(script) => {
|
||||||
|
if let Err(e) = webview.evaluate_script(&script) {
|
||||||
|
debug_eprintln!("{}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WebviewMessage::Navigate(url) => webview.load_url(url.as_str()),
|
||||||
|
WebviewMessage::Print => {
|
||||||
|
let _ = webview.print();
|
||||||
|
}
|
||||||
|
WebviewMessage::Close => {
|
||||||
|
windows.0.borrow_mut().get_mut(&window_id).map(|window| {
|
||||||
|
if let Some(i) = window.webviews.iter().position(|w| w.id == webview.id) {
|
||||||
|
window.webviews.remove(i);
|
||||||
|
}
|
||||||
|
window
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "ios")]
|
WebviewMessage::SetSize(size) => {
|
||||||
{
|
let mut bounds = webview.bounds();
|
||||||
use tao::platform::ios::WindowExtIOS;
|
let size = size.to_logical(window.scale_factor());
|
||||||
use wry::WebViewExtIOS;
|
bounds.width = size.width;
|
||||||
|
bounds.height = size.height;
|
||||||
|
|
||||||
f(Webview {
|
if let Some(b) = &webview.bounds {
|
||||||
webview: webview.inner.webview(),
|
let window_size = window.inner_size();
|
||||||
manager: webview.inner.manager(),
|
let mut bounds = b.lock().unwrap();
|
||||||
view_controller: window.ui_view_controller() as cocoa::base::id,
|
bounds.width_rate = size.width as f32 / window_size.width as f32;
|
||||||
});
|
bounds.height_rate = size.height as f32 / window_size.height as f32;
|
||||||
}
|
}
|
||||||
#[cfg(windows)]
|
|
||||||
{
|
|
||||||
f(Webview {
|
|
||||||
controller: webview.controller(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#[cfg(target_os = "android")]
|
|
||||||
{
|
|
||||||
f(webview.handle())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(debug_assertions, feature = "devtools"))]
|
webview.set_bounds(bounds);
|
||||||
WebviewMessage::OpenDevTools => {
|
}
|
||||||
webview.open_devtools();
|
WebviewMessage::SetPosition(position) => {
|
||||||
}
|
let mut bounds = webview.bounds();
|
||||||
#[cfg(any(debug_assertions, feature = "devtools"))]
|
let position = position.to_logical(window.scale_factor());
|
||||||
WebviewMessage::CloseDevTools => {
|
bounds.x = position.x;
|
||||||
webview.close_devtools();
|
bounds.y = position.y;
|
||||||
}
|
|
||||||
#[cfg(any(debug_assertions, feature = "devtools"))]
|
|
||||||
WebviewMessage::IsDevToolsOpen(tx) => {
|
|
||||||
tx.send(webview.is_devtools_open()).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getters
|
if let Some(b) = &webview.bounds {
|
||||||
WebviewMessage::Url(tx) => {
|
let window_size = window.inner_size();
|
||||||
tx.send(webview.url().parse().unwrap()).unwrap();
|
let mut bounds = b.lock().unwrap();
|
||||||
}
|
bounds.width_rate = position.x as f32 / window_size.width as f32;
|
||||||
WebviewMessage::Position(tx) => {
|
bounds.height_rate = position.y as f32 / window_size.height as f32;
|
||||||
let bounds = webview.bounds();
|
}
|
||||||
let position =
|
|
||||||
LogicalPosition::new(bounds.x, bounds.y).to_physical(window.scale_factor());
|
webview.set_bounds(bounds);
|
||||||
tx.send(position).unwrap();
|
}
|
||||||
}
|
// Getters
|
||||||
WebviewMessage::Size(tx) => {
|
WebviewMessage::Url(tx) => {
|
||||||
let bounds = webview.bounds();
|
tx.send(webview.url().parse().unwrap()).unwrap();
|
||||||
let size =
|
}
|
||||||
LogicalSize::new(bounds.width, bounds.height).to_physical(window.scale_factor());
|
WebviewMessage::Position(tx) => {
|
||||||
tx.send(size).unwrap();
|
let bounds = webview.bounds();
|
||||||
|
let position =
|
||||||
|
LogicalPosition::new(bounds.x, bounds.y).to_physical(window.scale_factor());
|
||||||
|
tx.send(position).unwrap();
|
||||||
|
}
|
||||||
|
WebviewMessage::Size(tx) => {
|
||||||
|
let bounds = webview.bounds();
|
||||||
|
let size =
|
||||||
|
LogicalSize::new(bounds.width, bounds.height).to_physical(window.scale_factor());
|
||||||
|
tx.send(size).unwrap();
|
||||||
|
}
|
||||||
|
WebviewMessage::SetFocus => {
|
||||||
|
webview.focus();
|
||||||
|
}
|
||||||
|
WebviewMessage::WithWebview(f) => {
|
||||||
|
#[cfg(any(
|
||||||
|
target_os = "linux",
|
||||||
|
target_os = "dragonfly",
|
||||||
|
target_os = "freebsd",
|
||||||
|
target_os = "netbsd",
|
||||||
|
target_os = "openbsd"
|
||||||
|
))]
|
||||||
|
{
|
||||||
|
f(webview.webview());
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
use wry::WebViewExtMacOS;
|
||||||
|
f(Webview {
|
||||||
|
webview: webview.webview(),
|
||||||
|
manager: webview.manager(),
|
||||||
|
ns_window: webview.ns_window(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "ios")]
|
||||||
|
{
|
||||||
|
use tao::platform::ios::WindowExtIOS;
|
||||||
|
use wry::WebViewExtIOS;
|
||||||
|
|
||||||
|
f(Webview {
|
||||||
|
webview: webview.inner.webview(),
|
||||||
|
manager: webview.inner.manager(),
|
||||||
|
view_controller: window.ui_view_controller() as cocoa::base::id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
f(Webview {
|
||||||
|
controller: webview.controller(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
{
|
||||||
|
f(webview.handle())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(debug_assertions, feature = "devtools"))]
|
||||||
|
WebviewMessage::OpenDevTools => {
|
||||||
|
webview.open_devtools();
|
||||||
|
}
|
||||||
|
#[cfg(any(debug_assertions, feature = "devtools"))]
|
||||||
|
WebviewMessage::CloseDevTools => {
|
||||||
|
webview.close_devtools();
|
||||||
|
}
|
||||||
|
#[cfg(any(debug_assertions, feature = "devtools"))]
|
||||||
|
WebviewMessage::IsDevToolsOpen(tx) => {
|
||||||
|
tx.send(webview.is_devtools_open()).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3341,7 +3419,7 @@ fn create_window<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
|
|||||||
webviews.push(create_webview(
|
webviews.push(create_webview(
|
||||||
WebviewKind::WindowContent,
|
WebviewKind::WindowContent,
|
||||||
&window,
|
&window,
|
||||||
window_id,
|
Arc::new(Mutex::new(window_id)),
|
||||||
webview_id,
|
webview_id,
|
||||||
context,
|
context,
|
||||||
webview,
|
webview,
|
||||||
@ -3390,7 +3468,7 @@ enum WebviewKind {
|
|||||||
WindowChild,
|
WindowChild,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct WebviewBounds {
|
struct WebviewBounds {
|
||||||
x_rate: f32,
|
x_rate: f32,
|
||||||
y_rate: f32,
|
y_rate: f32,
|
||||||
@ -3401,7 +3479,7 @@ struct WebviewBounds {
|
|||||||
fn create_webview<T: UserEvent>(
|
fn create_webview<T: UserEvent>(
|
||||||
kind: WebviewKind,
|
kind: WebviewKind,
|
||||||
window: &Window,
|
window: &Window,
|
||||||
window_id: WindowId,
|
window_id: Arc<Mutex<WindowId>>,
|
||||||
id: WebviewId,
|
id: WebviewId,
|
||||||
context: &Context<T>,
|
context: &Context<T>,
|
||||||
pending: PendingWebview<T, Wry<T>>,
|
pending: PendingWebview<T, Wry<T>>,
|
||||||
@ -3470,6 +3548,7 @@ fn create_webview<T: UserEvent>(
|
|||||||
|
|
||||||
if webview_attributes.file_drop_handler_enabled {
|
if webview_attributes.file_drop_handler_enabled {
|
||||||
let proxy = context.proxy.clone();
|
let proxy = context.proxy.clone();
|
||||||
|
let window_id_ = window_id.clone();
|
||||||
webview_builder = webview_builder.with_file_drop_handler(move |event| {
|
webview_builder = webview_builder.with_file_drop_handler(move |event| {
|
||||||
let event = match event {
|
let event = match event {
|
||||||
WryFileDropEvent::Hovered {
|
WryFileDropEvent::Hovered {
|
||||||
@ -3496,7 +3575,7 @@ fn create_webview<T: UserEvent>(
|
|||||||
WebviewMessage::WebviewEvent(WebviewEvent::FileDrop(event))
|
WebviewMessage::WebviewEvent(WebviewEvent::FileDrop(event))
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = proxy.send_event(Message::Webview(window_id, id, message));
|
let _ = proxy.send_event(Message::Webview(*window_id_.lock().unwrap(), id, message));
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -3598,7 +3677,7 @@ fn create_webview<T: UserEvent>(
|
|||||||
|
|
||||||
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
|
webview_builder = webview_builder.with_ipc_handler(create_ipc_handler(
|
||||||
kind,
|
kind,
|
||||||
window_id,
|
window_id.clone(),
|
||||||
id,
|
id,
|
||||||
context.clone(),
|
context.clone(),
|
||||||
label.clone(),
|
label.clone(),
|
||||||
@ -3696,12 +3775,13 @@ fn create_webview<T: UserEvent>(
|
|||||||
let controller = webview.controller();
|
let controller = webview.controller();
|
||||||
let proxy = context.proxy.clone();
|
let proxy = context.proxy.clone();
|
||||||
let proxy_ = proxy.clone();
|
let proxy_ = proxy.clone();
|
||||||
|
let window_id_ = window_id.clone();
|
||||||
let mut token = EventRegistrationToken::default();
|
let mut token = EventRegistrationToken::default();
|
||||||
unsafe {
|
unsafe {
|
||||||
controller.add_GotFocus(
|
controller.add_GotFocus(
|
||||||
&FocusChangedEventHandler::create(Box::new(move |_, _| {
|
&FocusChangedEventHandler::create(Box::new(move |_, _| {
|
||||||
let _ = proxy_.send_event(Message::Webview(
|
let _ = proxy.send_event(Message::Webview(
|
||||||
window_id,
|
*window_id_.lock().unwrap(),
|
||||||
id,
|
id,
|
||||||
WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(true)),
|
WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(true)),
|
||||||
));
|
));
|
||||||
@ -3714,8 +3794,8 @@ fn create_webview<T: UserEvent>(
|
|||||||
unsafe {
|
unsafe {
|
||||||
controller.add_LostFocus(
|
controller.add_LostFocus(
|
||||||
&FocusChangedEventHandler::create(Box::new(move |_, _| {
|
&FocusChangedEventHandler::create(Box::new(move |_, _| {
|
||||||
let _ = proxy.send_event(Message::Webview(
|
let _ = proxy_.send_event(Message::Webview(
|
||||||
window_id,
|
*window_id.lock().unwrap(),
|
||||||
id,
|
id,
|
||||||
WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(false)),
|
WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(false)),
|
||||||
));
|
));
|
||||||
@ -3745,7 +3825,7 @@ fn create_webview<T: UserEvent>(
|
|||||||
/// Create a wry ipc handler from a tauri ipc handler.
|
/// Create a wry ipc handler from a tauri ipc handler.
|
||||||
fn create_ipc_handler<T: UserEvent>(
|
fn create_ipc_handler<T: UserEvent>(
|
||||||
_kind: WebviewKind,
|
_kind: WebviewKind,
|
||||||
window_id: WindowId,
|
window_id: Arc<Mutex<WindowId>>,
|
||||||
webview_id: WebviewId,
|
webview_id: WebviewId,
|
||||||
context: Context<T>,
|
context: Context<T>,
|
||||||
label: String,
|
label: String,
|
||||||
@ -3754,7 +3834,7 @@ fn create_ipc_handler<T: UserEvent>(
|
|||||||
Box::new(move |request| {
|
Box::new(move |request| {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
if _kind == WebviewKind::WindowContent
|
if _kind == WebviewKind::WindowContent
|
||||||
&& undecorated_resizing::handle_request(context.clone(), window_id, &request)
|
&& undecorated_resizing::handle_request(context.clone(), *window_id.lock().unwrap(), &request)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3764,7 +3844,7 @@ fn create_ipc_handler<T: UserEvent>(
|
|||||||
DetachedWebview {
|
DetachedWebview {
|
||||||
label: label.clone(),
|
label: label.clone(),
|
||||||
dispatcher: WryWebviewDispatcher {
|
dispatcher: WryWebviewDispatcher {
|
||||||
window_id,
|
window_id: window_id.clone(),
|
||||||
webview_id,
|
webview_id,
|
||||||
context: context.clone(),
|
context: context.clone(),
|
||||||
},
|
},
|
||||||
|
@ -449,6 +449,9 @@ pub trait WebviewDispatch<T: UserEvent>: Debug + Clone + Send + Sync + Sized + '
|
|||||||
|
|
||||||
/// Executes javascript on the window this [`WindowDispatch`] represents.
|
/// Executes javascript on the window this [`WindowDispatch`] represents.
|
||||||
fn eval_script<S: Into<String>>(&self, script: S) -> Result<()>;
|
fn eval_script<S: Into<String>>(&self, script: S) -> Result<()>;
|
||||||
|
|
||||||
|
/// Moves the webview to the given window.
|
||||||
|
fn reparent(&self, window_id: WindowId) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Window dispatcher. A thread-safe handle to the window APIs.
|
/// Window dispatcher. A thread-safe handle to the window APIs.
|
||||||
|
@ -122,6 +122,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[
|
|||||||
("set_webview_position", false),
|
("set_webview_position", false),
|
||||||
("set_webview_focus", false),
|
("set_webview_focus", false),
|
||||||
("print", false),
|
("print", false),
|
||||||
|
("reparent", false),
|
||||||
// internal
|
// internal
|
||||||
("internal_toggle_devtools", true),
|
("internal_toggle_devtools", true),
|
||||||
],
|
],
|
||||||
|
@ -32,6 +32,14 @@ Enables the print command without any pre-configured scope.
|
|||||||
|
|
||||||
Denies the print command without any pre-configured scope.
|
Denies the print command without any pre-configured scope.
|
||||||
|
|
||||||
|
## allow-reparent
|
||||||
|
|
||||||
|
Enables the reparent command without any pre-configured scope.
|
||||||
|
|
||||||
|
## deny-reparent
|
||||||
|
|
||||||
|
Denies the reparent command without any pre-configured scope.
|
||||||
|
|
||||||
## allow-set-webview-focus
|
## allow-set-webview-focus
|
||||||
|
|
||||||
Enables the set_webview_focus command without any pre-configured scope.
|
Enables the set_webview_focus command without any pre-configured scope.
|
||||||
|
File diff suppressed because one or more lines are too long
@ -244,11 +244,13 @@ fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, labe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match invoke_message.unwrap_or_else(|| {
|
let message = invoke_message.unwrap_or_else(|| {
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
let _span = tracing::trace_span!("ipc::request::deserialize").entered();
|
let _span = tracing::trace_span!("ipc::request::deserialize").entered();
|
||||||
serde_json::from_str::<Message>(&message).map_err(Into::into)
|
serde_json::from_str::<Message>(&message).map_err(Into::into)
|
||||||
}) {
|
});
|
||||||
|
|
||||||
|
match message {
|
||||||
Ok(message) => {
|
Ok(message) => {
|
||||||
let request = InvokeRequest {
|
let request = InvokeRequest {
|
||||||
cmd: message.cmd,
|
cmd: message.cmd,
|
||||||
|
@ -540,6 +540,10 @@ impl<T: UserEvent> WebviewDispatch<T> for MockWebviewDispatcher {
|
|||||||
fn set_focus(&self) -> Result<()> {
|
fn set_focus(&self) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reparent(&self, window_id: WindowId) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {
|
impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {
|
||||||
|
@ -606,7 +606,7 @@ tauri::Builder::default()
|
|||||||
.webviews_lock()
|
.webviews_lock()
|
||||||
.values()
|
.values()
|
||||||
.map(|w| WebviewLabelDef {
|
.map(|w| WebviewLabelDef {
|
||||||
window_label: w.window.label().to_string(),
|
window_label: w.window().label().to_string(),
|
||||||
label: w.label().to_string(),
|
label: w.label().to_string(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -794,7 +794,10 @@ fn main() {
|
|||||||
/// Webview.
|
/// Webview.
|
||||||
#[default_runtime(crate::Wry, wry)]
|
#[default_runtime(crate::Wry, wry)]
|
||||||
pub struct Webview<R: Runtime> {
|
pub struct Webview<R: Runtime> {
|
||||||
pub(crate) window: Window<R>,
|
window_label: Arc<Mutex<String>>,
|
||||||
|
/// The manager to associate this webview with.
|
||||||
|
pub(crate) manager: Arc<AppManager<R>>,
|
||||||
|
pub(crate) app_handle: AppHandle<R>,
|
||||||
/// The webview created by the runtime.
|
/// The webview created by the runtime.
|
||||||
pub(crate) webview: DetachedWebview<EventLoopMessage, R>,
|
pub(crate) webview: DetachedWebview<EventLoopMessage, R>,
|
||||||
}
|
}
|
||||||
@ -802,7 +805,7 @@ pub struct Webview<R: Runtime> {
|
|||||||
impl<R: Runtime> std::fmt::Debug for Webview<R> {
|
impl<R: Runtime> std::fmt::Debug for Webview<R> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("Window")
|
f.debug_struct("Window")
|
||||||
.field("window", &self.window)
|
.field("window_label", &self.window_label)
|
||||||
.field("webview", &self.webview)
|
.field("webview", &self.webview)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
@ -811,7 +814,9 @@ impl<R: Runtime> std::fmt::Debug for Webview<R> {
|
|||||||
impl<R: Runtime> Clone for Webview<R> {
|
impl<R: Runtime> Clone for Webview<R> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
window: self.window.clone(),
|
window_label: self.window_label.clone(),
|
||||||
|
manager: self.manager.clone(),
|
||||||
|
app_handle: self.app_handle.clone(),
|
||||||
webview: self.webview.clone(),
|
webview: self.webview.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -836,7 +841,12 @@ impl<R: Runtime> PartialEq for Webview<R> {
|
|||||||
impl<R: Runtime> Webview<R> {
|
impl<R: Runtime> Webview<R> {
|
||||||
/// Create a new webview that is attached to the window.
|
/// Create a new webview that is attached to the window.
|
||||||
pub(crate) fn new(window: Window<R>, webview: DetachedWebview<EventLoopMessage, R>) -> Self {
|
pub(crate) fn new(window: Window<R>, webview: DetachedWebview<EventLoopMessage, R>) -> Self {
|
||||||
Self { window, webview }
|
Self {
|
||||||
|
window_label: Arc::new(Mutex::new(window.label().into())),
|
||||||
|
manager: window.manager.clone(),
|
||||||
|
app_handle: window.app_handle.clone(),
|
||||||
|
webview,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes a webview builder with the given window label and URL to load on the webview.
|
/// Initializes a webview builder with the given window label and URL to load on the webview.
|
||||||
@ -883,8 +893,9 @@ impl<R: Runtime> Webview<R> {
|
|||||||
|
|
||||||
/// Closes this webview.
|
/// Closes this webview.
|
||||||
pub fn close(&self) -> crate::Result<()> {
|
pub fn close(&self) -> crate::Result<()> {
|
||||||
if self.window.is_webview_window {
|
let window = self.window();
|
||||||
self.window.close()
|
if window.is_webview_window {
|
||||||
|
window.close()
|
||||||
} else {
|
} else {
|
||||||
self.webview.dispatcher.close()?;
|
self.webview.dispatcher.close()?;
|
||||||
self.manager().on_webview_close(self.label());
|
self.manager().on_webview_close(self.label());
|
||||||
@ -894,8 +905,9 @@ impl<R: Runtime> Webview<R> {
|
|||||||
|
|
||||||
/// Resizes this webview.
|
/// Resizes this webview.
|
||||||
pub fn set_size<S: Into<Size>>(&self, size: S) -> crate::Result<()> {
|
pub fn set_size<S: Into<Size>>(&self, size: S) -> crate::Result<()> {
|
||||||
if self.window.is_webview_window {
|
let window = self.window();
|
||||||
self.window.set_size(size.into())
|
if window.is_webview_window {
|
||||||
|
window.set_size(size.into())
|
||||||
} else {
|
} else {
|
||||||
self
|
self
|
||||||
.webview
|
.webview
|
||||||
@ -907,8 +919,9 @@ impl<R: Runtime> Webview<R> {
|
|||||||
|
|
||||||
/// Sets this webviews's position.
|
/// Sets this webviews's position.
|
||||||
pub fn set_position<Pos: Into<Position>>(&self, position: Pos) -> crate::Result<()> {
|
pub fn set_position<Pos: Into<Position>>(&self, position: Pos) -> crate::Result<()> {
|
||||||
if self.window.is_webview_window {
|
let window = self.window();
|
||||||
self.window.set_position(position.into())
|
if window.is_webview_window {
|
||||||
|
window.set_position(position.into())
|
||||||
} else {
|
} else {
|
||||||
self
|
self
|
||||||
.webview
|
.webview
|
||||||
@ -923,13 +936,23 @@ impl<R: Runtime> Webview<R> {
|
|||||||
self.webview.dispatcher.set_focus().map_err(Into::into)
|
self.webview.dispatcher.set_focus().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Move the webview to the given window.
|
||||||
|
pub fn reparent(&self, window: &Window<R>) -> crate::Result<()> {
|
||||||
|
let current_window = self.window();
|
||||||
|
if !current_window.is_webview_window {
|
||||||
|
self.webview.dispatcher.reparent(window.window.id)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the webview position.
|
/// Returns the webview position.
|
||||||
///
|
///
|
||||||
/// - For child webviews, returns the position of the top-left hand corner of the webviews's client area relative to the top-left hand corner of the parent window.
|
/// - For child webviews, returns the position of the top-left hand corner of the webviews's client area relative to the top-left hand corner of the parent window.
|
||||||
/// - For webview window, returns the inner position of the window.
|
/// - For webview window, returns the inner position of the window.
|
||||||
pub fn position(&self) -> crate::Result<PhysicalPosition<i32>> {
|
pub fn position(&self) -> crate::Result<PhysicalPosition<i32>> {
|
||||||
if self.window.is_webview_window {
|
let window = self.window();
|
||||||
self.window.inner_position()
|
if window.is_webview_window {
|
||||||
|
window.inner_position()
|
||||||
} else {
|
} else {
|
||||||
self.webview.dispatcher.position().map_err(Into::into)
|
self.webview.dispatcher.position().map_err(Into::into)
|
||||||
}
|
}
|
||||||
@ -937,8 +960,9 @@ impl<R: Runtime> Webview<R> {
|
|||||||
|
|
||||||
/// Returns the physical size of the webviews's client area.
|
/// Returns the physical size of the webviews's client area.
|
||||||
pub fn size(&self) -> crate::Result<PhysicalSize<u32>> {
|
pub fn size(&self) -> crate::Result<PhysicalSize<u32>> {
|
||||||
if self.window.is_webview_window {
|
let window = self.window();
|
||||||
self.window.inner_size()
|
if window.is_webview_window {
|
||||||
|
window.inner_size()
|
||||||
} else {
|
} else {
|
||||||
self.webview.dispatcher.size().map_err(Into::into)
|
self.webview.dispatcher.size().map_err(Into::into)
|
||||||
}
|
}
|
||||||
@ -948,8 +972,11 @@ impl<R: Runtime> Webview<R> {
|
|||||||
/// Webview APIs.
|
/// Webview APIs.
|
||||||
impl<R: Runtime> Webview<R> {
|
impl<R: Runtime> Webview<R> {
|
||||||
/// The window that is hosting this webview.
|
/// The window that is hosting this webview.
|
||||||
pub fn window(&self) -> &Window<R> {
|
pub fn window(&self) -> Window<R> {
|
||||||
&self.window
|
self
|
||||||
|
.manager
|
||||||
|
.get_window(&self.window_label.lock().unwrap())
|
||||||
|
.expect("could not locate webview parent window")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes a closure, providing it with the webview handle that is specific to the current platform.
|
/// Executes a closure, providing it with the webview handle that is specific to the current platform.
|
||||||
@ -1099,7 +1126,7 @@ fn main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(mobile)]
|
#[cfg(mobile)]
|
||||||
let app_handle = self.window.app_handle.clone();
|
let app_handle = self.app_handle.clone();
|
||||||
|
|
||||||
let message = InvokeMessage::new(
|
let message = InvokeMessage::new(
|
||||||
self,
|
self,
|
||||||
@ -1415,7 +1442,7 @@ tauri::Builder::default()
|
|||||||
where
|
where
|
||||||
F: Fn(Event) + Send + 'static,
|
F: Fn(Event) + Send + 'static,
|
||||||
{
|
{
|
||||||
self.window.manager.listen(
|
self.manager.listen(
|
||||||
event.into(),
|
event.into(),
|
||||||
EventTarget::Webview {
|
EventTarget::Webview {
|
||||||
label: self.label().to_string(),
|
label: self.label().to_string(),
|
||||||
@ -1454,7 +1481,7 @@ tauri::Builder::default()
|
|||||||
"####
|
"####
|
||||||
)]
|
)]
|
||||||
pub fn unlisten(&self, id: EventId) {
|
pub fn unlisten(&self, id: EventId) {
|
||||||
self.window.manager.unlisten(id)
|
self.manager.unlisten(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Listen to an event on this webview only once.
|
/// Listen to an event on this webview only once.
|
||||||
@ -1464,7 +1491,7 @@ tauri::Builder::default()
|
|||||||
where
|
where
|
||||||
F: FnOnce(Event) + Send + 'static,
|
F: FnOnce(Event) + Send + 'static,
|
||||||
{
|
{
|
||||||
self.window.manager.once(
|
self.manager.once(
|
||||||
event.into(),
|
event.into(),
|
||||||
EventTarget::Webview {
|
EventTarget::Webview {
|
||||||
label: self.label().to_string(),
|
label: self.label().to_string(),
|
||||||
@ -1478,19 +1505,19 @@ impl<R: Runtime> Manager<R> for Webview<R> {}
|
|||||||
|
|
||||||
impl<R: Runtime> ManagerBase<R> for Webview<R> {
|
impl<R: Runtime> ManagerBase<R> for Webview<R> {
|
||||||
fn manager(&self) -> &AppManager<R> {
|
fn manager(&self) -> &AppManager<R> {
|
||||||
&self.window.manager
|
&self.manager
|
||||||
}
|
}
|
||||||
|
|
||||||
fn manager_owned(&self) -> Arc<AppManager<R>> {
|
fn manager_owned(&self) -> Arc<AppManager<R>> {
|
||||||
self.window.manager.clone()
|
self.manager.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runtime(&self) -> RuntimeOrDispatch<'_, R> {
|
fn runtime(&self) -> RuntimeOrDispatch<'_, R> {
|
||||||
self.window.app_handle.runtime()
|
self.app_handle.runtime()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn managed_app_handle(&self) -> &AppHandle<R> {
|
fn managed_app_handle(&self) -> &AppHandle<R> {
|
||||||
&self.window.app_handle
|
&self.app_handle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +159,19 @@ mod desktop_commands {
|
|||||||
setter!(set_webview_position, set_position, Position);
|
setter!(set_webview_position, set_position, Position);
|
||||||
setter!(set_webview_focus, set_focus);
|
setter!(set_webview_focus, set_focus);
|
||||||
|
|
||||||
|
#[command(root = "crate")]
|
||||||
|
pub async fn reparent<R: Runtime>(
|
||||||
|
webview: crate::Webview<R>,
|
||||||
|
label: Option<String>,
|
||||||
|
window: String,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let webview = get_webview(webview, label)?;
|
||||||
|
if let Some(window) = webview.manager.get_window(&window) {
|
||||||
|
webview.reparent(&window)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(debug_assertions, feature = "devtools"))]
|
#[cfg(any(debug_assertions, feature = "devtools"))]
|
||||||
#[command(root = "crate")]
|
#[command(root = "crate")]
|
||||||
pub async fn internal_toggle_devtools<R: Runtime>(
|
pub async fn internal_toggle_devtools<R: Runtime>(
|
||||||
@ -227,6 +240,7 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
|||||||
desktop_commands::set_webview_position,
|
desktop_commands::set_webview_position,
|
||||||
desktop_commands::set_webview_focus,
|
desktop_commands::set_webview_focus,
|
||||||
desktop_commands::print,
|
desktop_commands::print,
|
||||||
|
desktop_commands::reparent,
|
||||||
#[cfg(any(debug_assertions, feature = "devtools"))]
|
#[cfg(any(debug_assertions, feature = "devtools"))]
|
||||||
desktop_commands::internal_toggle_devtools,
|
desktop_commands::internal_toggle_devtools,
|
||||||
]);
|
]);
|
||||||
|
@ -572,7 +572,7 @@ impl<'a, R: Runtime, M: Manager<R>> WebviewWindowBuilder<'a, R, M> {
|
|||||||
/// - **Linux**: This makes the new window transient for parent, see <https://docs.gtk.org/gtk3/method.Window.set_transient_for.html>
|
/// - **Linux**: This makes the new window transient for parent, see <https://docs.gtk.org/gtk3/method.Window.set_transient_for.html>
|
||||||
/// - **macOS**: This adds the window as a child of parent, see <https://developer.apple.com/documentation/appkit/nswindow/1419152-addchildwindow?language=objc>
|
/// - **macOS**: This adds the window as a child of parent, see <https://developer.apple.com/documentation/appkit/nswindow/1419152-addchildwindow?language=objc>
|
||||||
pub fn parent(mut self, parent: &WebviewWindow<R>) -> crate::Result<Self> {
|
pub fn parent(mut self, parent: &WebviewWindow<R>) -> crate::Result<Self> {
|
||||||
self.window_builder = self.window_builder.parent(&parent.webview.window)?;
|
self.window_builder = self.window_builder.parent(&parent.webview.window())?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,7 +586,7 @@ impl<'a, R: Runtime, M: Manager<R>> WebviewWindowBuilder<'a, R, M> {
|
|||||||
/// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows>
|
/// For more information, see <https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows>
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub fn owner(mut self, owner: &WebviewWindow<R>) -> crate::Result<Self> {
|
pub fn owner(mut self, owner: &WebviewWindow<R>) -> crate::Result<Self> {
|
||||||
self.window_builder = self.window_builder.owner(&owner.webview.window)?;
|
self.window_builder = self.window_builder.owner(&owner.webview.window())?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,7 +638,9 @@ impl<'a, R: Runtime, M: Manager<R>> WebviewWindowBuilder<'a, R, M> {
|
|||||||
target_os = "openbsd"
|
target_os = "openbsd"
|
||||||
))]
|
))]
|
||||||
pub fn transient_for(mut self, parent: &WebviewWindow<R>) -> crate::Result<Self> {
|
pub fn transient_for(mut self, parent: &WebviewWindow<R>) -> crate::Result<Self> {
|
||||||
self.window_builder = self.window_builder.transient_for(&parent.webview.window)?;
|
self.window_builder = self
|
||||||
|
.window_builder
|
||||||
|
.transient_for(&parent.webview.window())?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -868,7 +870,9 @@ impl<R: Runtime> raw_window_handle::HasWindowHandle for WebviewWindow<R> {
|
|||||||
fn window_handle(
|
fn window_handle(
|
||||||
&self,
|
&self,
|
||||||
) -> std::result::Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
|
) -> std::result::Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
|
||||||
self.webview.window().window_handle()
|
Ok(unsafe {
|
||||||
|
raw_window_handle::WindowHandle::borrow_raw(self.webview.window().window_handle()?.as_raw())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,7 +333,7 @@ tauri::Builder::default()
|
|||||||
.webviews_lock()
|
.webviews_lock()
|
||||||
.values()
|
.values()
|
||||||
.map(|w| WebviewLabelDef {
|
.map(|w| WebviewLabelDef {
|
||||||
window_label: w.window.label().to_string(),
|
window_label: w.window().label().to_string(),
|
||||||
label: w.label().to_string(),
|
label: w.label().to_string(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -988,7 +988,7 @@ impl<R: Runtime> Window<R> {
|
|||||||
.webview
|
.webview
|
||||||
.webviews_lock()
|
.webviews_lock()
|
||||||
.values()
|
.values()
|
||||||
.filter(|w| w.window() == self)
|
.filter(|w| &w.window() == self)
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import {
|
|||||||
} from './event'
|
} from './event'
|
||||||
import { invoke } from './core'
|
import { invoke } from './core'
|
||||||
import { Window, getCurrent as getCurrentWindow } from './window'
|
import { Window, getCurrent as getCurrentWindow } from './window'
|
||||||
|
import { WebviewWindow } from './webviewWindow'
|
||||||
|
|
||||||
interface FileDropPayload {
|
interface FileDropPayload {
|
||||||
paths: string[]
|
paths: string[]
|
||||||
@ -474,6 +475,23 @@ class Webview {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves this webview to the given label.
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* import { getCurrent } from '@tauri-apps/api/webview';
|
||||||
|
* await getCurrent().reparent('other-window');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @returns A promise indicating the success or failure of the operation.
|
||||||
|
*/
|
||||||
|
async reparent(window: Window | WebviewWindow | string): Promise<void> {
|
||||||
|
return invoke('plugin:webview|set_webview_focus', {
|
||||||
|
label: this.label,
|
||||||
|
window: typeof window === 'string' ? window : window.label
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user