Skip to content

Commit 222a96b

Browse files
authored
fix(core): multiwebview mode fixes for auto resize, reparent and add_child (#8999)
* refactor(core): simplify multiwebview impl, fix autoresize * add_child on main thread * fix reparent * revert some changes * add change files
1 parent de38c31 commit 222a96b

File tree

11 files changed

+76
-38
lines changed

11 files changed

+76
-38
lines changed

.changes/fix-add-child-deadlock.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch:bug
3+
---
4+
5+
Fixes `Window::add_child` deadlock.

.changes/fix-reparent.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch:bug
3+
---
4+
5+
Fixes `Webview::reparent` not updating the webview parent window reference.

.changes/multiwebview-bounds-fixes.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-runtime-wry": patch:bug
3+
---
4+
5+
Fixes auto resize and positioning when using the multiwebview mode.

core/tauri-runtime-wry/src/lib.rs

+23-20
Original file line numberDiff line numberDiff line change
@@ -2829,10 +2829,10 @@ fn handle_user_message<T: UserEvent>(
28292829
bounds.height = size.height;
28302830

28312831
if let Some(b) = &webview.bounds {
2832-
let window_size = window.inner_size();
2832+
let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
28332833
let mut bounds = b.lock().unwrap();
2834-
bounds.width_rate = size.width as f32 / window_size.width as f32;
2835-
bounds.height_rate = size.height as f32 / window_size.height as f32;
2834+
bounds.width_rate = size.width as f32 / window_size.width;
2835+
bounds.height_rate = size.height as f32 / window_size.height;
28362836
}
28372837

28382838
webview.set_bounds(bounds);
@@ -2844,10 +2844,11 @@ fn handle_user_message<T: UserEvent>(
28442844
bounds.y = position.y;
28452845

28462846
if let Some(b) = &webview.bounds {
2847-
let window_size = window.inner_size();
2847+
let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
28482848
let mut bounds = b.lock().unwrap();
2849-
bounds.width_rate = position.x as f32 / window_size.width as f32;
2850-
bounds.height_rate = position.y as f32 / window_size.height as f32;
2849+
2850+
bounds.x_rate = position.x as f32 / window_size.width;
2851+
bounds.y_rate = position.y as f32 / window_size.height;
28512852
}
28522853

28532854
webview.set_bounds(bounds);
@@ -2913,7 +2914,6 @@ fn handle_user_message<T: UserEvent>(
29132914
f(webview.handle())
29142915
}
29152916
}
2916-
29172917
#[cfg(any(debug_assertions, feature = "devtools"))]
29182918
WebviewMessage::OpenDevTools => {
29192919
webview.open_devtools();
@@ -2940,6 +2940,7 @@ fn handle_user_message<T: UserEvent>(
29402940
Ok(webview) => {
29412941
windows.0.borrow_mut().get_mut(&window_id).map(|w| {
29422942
w.webviews.push(webview);
2943+
w.has_children.store(true, Ordering::Relaxed);
29432944
w
29442945
});
29452946
}
@@ -3181,20 +3182,21 @@ fn handle_event_loop<T: UserEvent>(
31813182
}
31823183
}
31833184
TaoWindowEvent::Resized(size) => {
3184-
if let Some(webviews) = windows
3185+
if let Some((Some(window), webviews)) = windows
31853186
.0
31863187
.borrow()
31873188
.get(&window_id)
3188-
.map(|w| w.webviews.clone())
3189+
.map(|w| (w.inner.clone(), w.webviews.clone()))
31893190
{
3191+
let size = size.to_logical::<f32>(window.scale_factor());
31903192
for webview in webviews {
31913193
if let Some(bounds) = &webview.bounds {
31923194
let b = bounds.lock().unwrap();
31933195
webview.set_bounds(wry::Rect {
3194-
x: (size.width as f32 * b.x_rate) as i32,
3195-
y: (size.height as f32 * b.y_rate) as i32,
3196-
width: (size.width as f32 * b.width_rate) as u32,
3197-
height: (size.height as f32 * b.height_rate) as u32,
3196+
x: (size.width * b.x_rate) as i32,
3197+
y: (size.height * b.y_rate) as i32,
3198+
width: (size.width * b.width_rate) as u32,
3199+
height: (size.height * b.height_rate) as u32,
31983200
});
31993201
}
32003202
}
@@ -3594,7 +3596,8 @@ fn create_webview<T: UserEvent>(
35943596

35953597
if let Some(navigation_handler) = pending.navigation_handler {
35963598
webview_builder = webview_builder.with_navigation_handler(move |url| {
3597-
Url::parse(&url)
3599+
url
3600+
.parse()
35983601
.map(|url| navigation_handler(&url))
35993602
.unwrap_or(true)
36003603
});
@@ -3610,14 +3613,14 @@ fn create_webview<T: UserEvent>(
36103613
height: size.height,
36113614
});
36123615

3613-
let window_size = window.inner_size();
3616+
let window_size = window.inner_size().to_logical::<f32>(window.scale_factor());
36143617

36153618
if webview_attributes.auto_resize {
36163619
Some(WebviewBounds {
3617-
x_rate: (position.x as f32) / window_size.width as f32,
3618-
y_rate: (position.y as f32) / window_size.height as f32,
3619-
width_rate: (size.width as f32) / window_size.width as f32,
3620-
height_rate: (size.height as f32) / window_size.height as f32,
3620+
x_rate: (position.x as f32) / window_size.width,
3621+
y_rate: (position.y as f32) / window_size.height,
3622+
width_rate: (size.width as f32) / window_size.width,
3623+
height_rate: (size.height as f32) / window_size.height,
36213624
})
36223625
} else {
36233626
None
@@ -3647,7 +3650,7 @@ fn create_webview<T: UserEvent>(
36473650

36483651
if let Some(page_load_handler) = pending.on_page_load_handler {
36493652
webview_builder = webview_builder.with_on_page_load_handler(move |event, url| {
3650-
let _ = Url::parse(&url).map(|url| {
3653+
let _ = url.parse().map(|url| {
36513654
page_load_handler(
36523655
url,
36533656
match event {

core/tauri/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ serde = { version = "1.0", features = [ "derive", "rc" ] }
4747
tokio = { version = "1", features = [ "rt", "rt-multi-thread", "sync", "fs", "io-util" ] }
4848
futures-util = "0.3"
4949
uuid = { version = "1", features = [ "v4" ], optional = true }
50-
url = { version = "2.4" }
50+
url = "2"
5151
anyhow = "1.0"
5252
thiserror = "1.0"
5353
tauri-runtime = { version = "2.0.0-beta.5", path = "../tauri-runtime" }

core/tauri/src/error.rs

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ pub enum Error {
4040
/// Webview label must be unique.
4141
#[error("a webview with label `{0}` already exists")]
4242
WebviewLabelAlreadyExists(String),
43+
/// Cannot use the webview reparent function on webview windows.
44+
#[error("cannot reparent when using a WebviewWindow")]
45+
CannotReparentWebviewWindow,
4346
/// Embedded asset not found.
4447
#[error("asset not found: {0}")]
4548
AssetNotFound(String),

core/tauri/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -804,7 +804,7 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
804804
/// Fetch a single webview window from the manager.
805805
fn get_webview_window(&self, label: &str) -> Option<WebviewWindow<R>> {
806806
self.manager().get_webview(label).and_then(|webview| {
807-
if webview.window().is_webview_window {
807+
if webview.window().is_webview_window() {
808808
Some(WebviewWindow { webview })
809809
} else {
810810
None
@@ -819,7 +819,7 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
819819
.webviews()
820820
.into_iter()
821821
.filter_map(|(label, webview)| {
822-
if webview.window().is_webview_window {
822+
if webview.window().is_webview_window() {
823823
Some((label, WebviewWindow { webview }))
824824
} else {
825825
None

core/tauri/src/manager/window.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ impl<R: Runtime> WindowManager<R> {
7979
&self,
8080
app_handle: AppHandle<R>,
8181
window: DetachedWindow<EventLoopMessage, R>,
82-
multiwebview: bool,
82+
is_webview_window: bool,
8383
#[cfg(desktop)] menu: Option<crate::window::WindowMenu<R>>,
8484
) -> Window<R> {
8585
let window = Window::new(
@@ -88,7 +88,7 @@ impl<R: Runtime> WindowManager<R> {
8888
app_handle,
8989
#[cfg(desktop)]
9090
menu,
91-
multiwebview,
91+
is_webview_window,
9292
);
9393

9494
let window_ = window.clone();
@@ -197,7 +197,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
197197
WindowEvent::FileDrop(event) => match event {
198198
FileDropEvent::Hovered { paths, position } => {
199199
let payload = FileDropPayload { paths, position };
200-
if window.is_webview_window {
200+
if window.is_webview_window() {
201201
window.emit_to(
202202
EventTarget::labeled(window.label()),
203203
DROP_HOVER_EVENT,
@@ -218,14 +218,14 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
218218
}
219219
let payload = FileDropPayload { paths, position };
220220

221-
if window.is_webview_window {
221+
if window.is_webview_window() {
222222
window.emit_to(EventTarget::labeled(window.label()), DROP_EVENT, payload)?
223223
} else {
224224
window.emit_to_window(DROP_EVENT, payload)?
225225
}
226226
}
227227
FileDropEvent::Cancelled => {
228-
if window.is_webview_window {
228+
if window.is_webview_window() {
229229
window.emit_to(
230230
EventTarget::labeled(window.label()),
231231
DROP_CANCELLED_EVENT,

core/tauri/src/webview/mod.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ impl<R: Runtime> Webview<R> {
894894
/// Closes this webview.
895895
pub fn close(&self) -> crate::Result<()> {
896896
let window = self.window();
897-
if window.is_webview_window {
897+
if window.is_webview_window() {
898898
window.close()
899899
} else {
900900
self.webview.dispatcher.close()?;
@@ -906,7 +906,7 @@ impl<R: Runtime> Webview<R> {
906906
/// Resizes this webview.
907907
pub fn set_size<S: Into<Size>>(&self, size: S) -> crate::Result<()> {
908908
let window = self.window();
909-
if window.is_webview_window {
909+
if window.is_webview_window() {
910910
window.set_size(size.into())
911911
} else {
912912
self
@@ -920,7 +920,7 @@ impl<R: Runtime> Webview<R> {
920920
/// Sets this webviews's position.
921921
pub fn set_position<Pos: Into<Position>>(&self, position: Pos) -> crate::Result<()> {
922922
let window = self.window();
923-
if window.is_webview_window {
923+
if window.is_webview_window() {
924924
window.set_position(position.into())
925925
} else {
926926
self
@@ -939,10 +939,13 @@ impl<R: Runtime> Webview<R> {
939939
/// Move the webview to the given window.
940940
pub fn reparent(&self, window: &Window<R>) -> crate::Result<()> {
941941
let current_window = self.window();
942-
if !current_window.is_webview_window {
942+
if current_window.is_webview_window() || window.is_webview_window() {
943+
Err(crate::Error::CannotReparentWebviewWindow)
944+
} else {
943945
self.webview.dispatcher.reparent(window.window.id)?;
946+
*self.window_label.lock().unwrap() = window.label().to_string();
947+
Ok(())
944948
}
945-
Ok(())
946949
}
947950

948951
/// Returns the webview position.
@@ -951,7 +954,7 @@ impl<R: Runtime> Webview<R> {
951954
/// - For webview window, returns the inner position of the window.
952955
pub fn position(&self) -> crate::Result<PhysicalPosition<i32>> {
953956
let window = self.window();
954-
if window.is_webview_window {
957+
if window.is_webview_window() {
955958
window.inner_position()
956959
} else {
957960
self.webview.dispatcher.position().map_err(Into::into)
@@ -961,7 +964,7 @@ impl<R: Runtime> Webview<R> {
961964
/// Returns the physical size of the webviews's client area.
962965
pub fn size(&self) -> crate::Result<PhysicalSize<u32>> {
963966
let window = self.window();
964-
if window.is_webview_window {
967+
if window.is_webview_window() {
965968
window.inner_size()
966969
} else {
967970
self.webview.dispatcher.size().map_err(Into::into)

core/tauri/src/webview/webview_window.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ impl<'de, R: Runtime> CommandArg<'de, R> for WebviewWindow<R> {
880880
/// Grabs the [`Window`] from the [`CommandItem`]. This will never fail.
881881
fn from_command(command: CommandItem<'de, R>) -> Result<Self, InvokeError> {
882882
let webview = command.message.webview();
883-
if webview.window().is_webview_window {
883+
if webview.window().is_webview_window() {
884884
Ok(Self { webview })
885885
} else {
886886
Err(InvokeError::from_anyhow(anyhow::anyhow!(

core/tauri/src/window/mod.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,7 @@ pub struct Window<R: Runtime> {
866866
#[cfg(desktop)]
867867
pub(crate) menu: Arc<std::sync::Mutex<Option<WindowMenu<R>>>>,
868868
/// Whether this window is a Webview window (hosts only a single webview) or a container for multiple webviews
869-
pub(crate) is_webview_window: bool,
869+
is_webview_window: bool,
870870
}
871871

872872
impl<R: Runtime> std::fmt::Debug for Window<R> {
@@ -981,7 +981,17 @@ impl<R: Runtime> Window<R> {
981981
position: P,
982982
size: S,
983983
) -> crate::Result<Webview<R>> {
984-
webview_builder.build(self.clone(), position.into(), size.into())
984+
use std::sync::mpsc::channel;
985+
986+
let (tx, rx) = channel();
987+
let position = position.into();
988+
let size = size.into();
989+
let window_ = self.clone();
990+
self.run_on_main_thread(move || {
991+
let res = webview_builder.build(window_, position, size);
992+
tx.send(res.map_err(Into::into)).unwrap();
993+
})?;
994+
rx.recv().unwrap()
985995
}
986996

987997
/// List of webviews associated with this window.
@@ -996,6 +1006,10 @@ impl<R: Runtime> Window<R> {
9961006
.collect()
9971007
}
9981008

1009+
pub(crate) fn is_webview_window(&self) -> bool {
1010+
self.is_webview_window
1011+
}
1012+
9991013
/// Runs the given closure on the main thread.
10001014
pub fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> crate::Result<()> {
10011015
self

0 commit comments

Comments
 (0)