From 3e7ba372edd8b33dc138356e69bb36a88b5e9906 Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 9 Jun 2026 20:52:04 +0800 Subject: [PATCH 1/4] fix: wait for window creation no matter if on main thread --- crates/tauri-runtime-wry/src/lib.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index 927cbea1e2a5..08417a5e2de0 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -317,6 +317,7 @@ impl Context { }) .unwrap_or((None, false)); + let (tx, rx) = channel(); send_user_message( self, Message::CreateWindow( @@ -331,8 +332,10 @@ impl Context { after_window_creation, ) }), + tx, ), )?; + rx.recv().unwrap()?; let dispatcher = WryWindowDispatcher { window_id, @@ -1567,7 +1570,7 @@ pub enum Message { Webview(WindowId, WebviewId, WebviewMessage), EventLoopWindowTarget(EventLoopWindowTargetMessage), CreateWebview(WindowId, CreateWebviewClosure), - CreateWindow(WindowId, CreateWindowClosure), + CreateWindow(WindowId, CreateWindowClosure, Sender>), CreateRawWindow( WindowId, Box (String, TaoWindowBuilder) + Send>, @@ -4080,12 +4083,13 @@ fn handle_user_message( } } } - Message::CreateWindow(window_id, handler) => match handler(event_loop) { + Message::CreateWindow(window_id, handler, sender) => match handler(event_loop) { Ok(webview) => { windows.0.borrow_mut().insert(window_id, webview); + sender.send(Ok(())).unwrap(); } Err(e) => { - log::error!("{e}"); + sender.send(Err(e)).unwrap(); } }, Message::CreateRawWindow(window_id, handler, sender) => { From 47b5df4788ebb67cc3ae55cecc12fdb84ce2366e Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 9 Jun 2026 21:10:00 +0800 Subject: [PATCH 2/4] Add change file --- .changes/wait-async-window-creation.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changes/wait-async-window-creation.md diff --git a/.changes/wait-async-window-creation.md b/.changes/wait-async-window-creation.md new file mode 100644 index 000000000000..9aad71bf2df6 --- /dev/null +++ b/.changes/wait-async-window-creation.md @@ -0,0 +1,5 @@ +--- +"tauri-runtime-wry": patch:bug +--- + +`create_window` should wait for the window creation to complete before returning even if it's off main thread, it should also return the error if it failed From 501816ae30073919e5751249944ccd8ce751a87a Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 9 Jun 2026 21:12:53 +0800 Subject: [PATCH 3/4] Avoid unwrap --- crates/tauri-runtime-wry/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index 08417a5e2de0..85e90d91e322 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -335,7 +335,8 @@ impl Context { tx, ), )?; - rx.recv().unwrap()?; + rx.recv() + .map_err(|_| crate::Error::FailedToReceiveMessage)??; let dispatcher = WryWindowDispatcher { window_id, @@ -4086,9 +4087,11 @@ fn handle_user_message( Message::CreateWindow(window_id, handler, sender) => match handler(event_loop) { Ok(webview) => { windows.0.borrow_mut().insert(window_id, webview); + // SAFETY: The caller calls blocking `rx.recv()` so the receiver will never be dropped before this sender.send(Ok(())).unwrap(); } Err(e) => { + // SAFETY: The caller calls blocking `rx.recv()` so the receiver will never be dropped before this sender.send(Err(e)).unwrap(); } }, From 789d2152d0050bc4e65d41d4a49f752f8bf8d765 Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 9 Jun 2026 21:25:39 +0800 Subject: [PATCH 4/4] Same for `create_webview` --- .changes/wait-async-window-creation.md | 2 +- crates/tauri-runtime-wry/src/lib.rs | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.changes/wait-async-window-creation.md b/.changes/wait-async-window-creation.md index 9aad71bf2df6..f1d5252fe45c 100644 --- a/.changes/wait-async-window-creation.md +++ b/.changes/wait-async-window-creation.md @@ -2,4 +2,4 @@ "tauri-runtime-wry": patch:bug --- -`create_window` should wait for the window creation to complete before returning even if it's off main thread, it should also return the error if it failed +`create_window` and `create_webview` should wait for the window creation to complete before returning even if it's off main thread, it should also return the error if it failed diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index 85e90d91e322..f0e497b1a106 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -379,6 +379,7 @@ impl Context { let window_id_wrapper = Arc::new(Mutex::new(window_id)); let window_id_wrapper_ = window_id_wrapper.clone(); + let (tx, rx) = channel(); send_user_message( self, Message::CreateWebview( @@ -394,8 +395,11 @@ impl Context { options.focused_webview, ) }), + tx, ), )?; + rx.recv() + .map_err(|_| crate::Error::FailedToReceiveMessage)??; let dispatcher = WryWebviewDispatcher { window_id: window_id_wrapper, @@ -1570,7 +1574,7 @@ pub enum Message { Window(WindowId, WindowMessage), Webview(WindowId, WebviewId, WebviewMessage), EventLoopWindowTarget(EventLoopWindowTargetMessage), - CreateWebview(WindowId, CreateWebviewClosure), + CreateWebview(WindowId, CreateWebviewClosure, Sender>), CreateWindow(WindowId, CreateWindowClosure, Sender>), CreateRawWindow( WindowId, @@ -4062,7 +4066,7 @@ fn handle_user_message( } } } - Message::CreateWebview(window_id, handler) => { + Message::CreateWebview(window_id, handler, sender) => { let window = windows .0 .borrow() @@ -4077,9 +4081,12 @@ fn handle_user_message( w.has_children.store(true, Ordering::Relaxed); w }); + // SAFETY: The caller calls blocking `rx.recv()` so the receiver will never be dropped before this + sender.send(Ok(())).unwrap(); } Err(e) => { - log::error!("{e}"); + // SAFETY: The caller calls blocking `rx.recv()` so the receiver will never be dropped before this + sender.send(Err(e)).unwrap(); } } }