I’m developing a desktop app with Rust + Tauri (v2.5) + SvelteKit.
On macOS my command for opening a new settings window works perfectly. On Windows however, the app freezes when building the window: I see log #1 and #2, but never #3 or #4. The window appears, but it is blank white and the whole app becomes unresponsive.
Here is the relevant Rust code:
#[tauri::command]
pub fn open_settings_window(app: AppHandle) -> tauri::Result<()> {
if let Some(win) = app.get_webview_window("settings") {
win.set_focus()?;
win.show()?;
return Ok(());
}
println!("#1");
let webview_url = WebviewUrl::App("settings".into());
let mut builder = WebviewWindowBuilder::new(
&app,
"settings",
webview_url,
)
.title("Settings")
.resizable(false)
.maximizable(false)
.minimizable(false)
.decorations(true)
.inner_size(800.0, 600.0)
.center();
#[cfg(target_os = "macos")]
{
builder = builder.title_bar_style(TitleBarStyle::Overlay)
}
println!("#2");
if let Ok(win) = builder.build() {
println!("#3");
let _ = win.show();
}
println!("#4");
Ok(())
}
And on the SvelteKit side I call it like this:
import { invoke } from "@tauri-apps/api/core";
export async function openSettingsWindow() {
await invoke("open_settings_window");
}
// Button
<button on:click={openSettingsWindow}>Open Settings</button>
Problem:
Question:
Environment:
Here's my directory tree
├── +layout.svelte
├── +layout.ts
├── +page.svelte
└── settings
├── +layout.svelte
├── +layout.ts
└── +page.svelte
PS:
I have also tried /settings and /settings/index.html but neither of them works.
Edit (package.json):
{
"name": "myUIApp",
"version": "0.1.0",
"description": "",
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"tauri": "tauri"
},
"license": "MIT",
"dependencies": {
"@iconify-icons/heroicons-solid": "^1.2.6",
"@iconify-icons/mdi": "^1.2.48",
"@tailwindcss/vite": "^4.1.3",
"@tauri-apps/api": "^2.5.0",
"@tauri-apps/plugin-dialog": "^2.2.2",
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-os": "~2",
"@tauri-apps/plugin-shell": "^2.3.0",
"echarts": "^5.6.0",
"echarts-stat": "^1.2.0",
"plotly.js-dist": "^3.0.3",
"plotly.js-dist-min": "^3.0.3",
"svelte-i18n": "^4.0.1",
"svelte-tiny-virtual-list": "^3.0.0"
},
"devDependencies": {
"@iconify-json/heroicons": "^1.2.2",
"@iconify-json/mdi": "^1.2.3",
"@iconify-json/tabler": "^1.2.19",
"@iconify/svelte": "^5.0.0",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.9.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tailwindcss/postcss": "^4.1.3",
"@tauri-apps/cli": "^2",
"autoprefixer": "^10.4.21",
"postcss": "^8.5.4",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"svelte-preprocess": "^6.0.3",
"tailwindcss": "^4.1.8",
"typescript": "~5.6.2",
"vite": "^6.0.3"
}
}
According to the docs of WebviewWindowBuilder::new:
Known issues
On Windows, this function deadlocks when used in a synchronous command and event handlers, see the Webview2 issue. You should use async commands and separate threads when creating windows.
Their suggested code is
tauri::Builder::default()
.setup(|app| {
let handle = app.handle().clone();
std::thread::spawn(move || {
let webview_window = tauri::WebviewWindowBuilder::new(&handle, "label", tauri::WebviewUrl::App("index.html".into()))
.build()
.unwrap();
});
Ok(())
});
or
#[tauri::command]
async fn create_window(app: tauri::AppHandle) {
let webview_window = tauri::WebviewWindowBuilder::new(&app, "label", tauri::WebviewUrl::App("index.html".into()))
.build()
.unwrap();
}