Obtener la ventana, desde los dos lados
Ventana, webview y la combinación de las dos: tres tipos que en Tauri 2 son cosas distintas. Cómo se consigue cada uno desde Rust y desde el frontend, y por qué la distinción deja de ser académica en cuanto hay dos webviews.
Los tres tipos
La regla para saber a cuál pertenece una operación es intuitiva en cuanto se ve así: si el sistema operativo lo entiende, es de la ventana; si el motor del navegador lo entiende, es de la webview.
Desde Rust
En el gancho de inicialización, a través del manejador de la aplicación:
.setup(|app| { // La ventana declarada en la configuración ya existe aquí. Nivel 4.2. let win = app.get_webview_window("main") .expect("la ventana 'main' está declarada en tauri.conf.json"); win.set_title("Catálogo — sin proyecto")?; Ok(())})En un comando, hay tres formas y conviene elegir bien:
// 1 · la ventana que hizo la llamada. La más precisa cuando hay varias.#[tauri::command]async fn cerrar(window: tauri::WebviewWindow) -> Result<(), ErrorPayload> { window.close().map_err(...)}// 2 · una ventana concreta por su etiqueta, a través del manejador.#[tauri::command]async fn enfocar_ajustes(app: tauri::AppHandle) -> Result<(), ErrorPayload> { if let Some(w) = app.get_webview_window("settings") { w.set_focus()...; } Ok(())}// 3 · todas.#[tauri::command]async fn cerrar_todas(app: tauri::AppHandle) { for (_etiqueta, w) in app.webview_windows() { let _ = w.close(); }}La primera es la que se olvida y la que más se necesita: el framework inyecta la ventana que originó la llamada sin que el frontend tenga que decir cuál es. Eso importa porque un frontend que envía su propia etiqueta puede enviar la de otra, y ahí hay un borde de confianza. El nivel 16 vuelve sobre los argumentos inyectados.
Desde el frontend
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';const win = getCurrentWebviewWindow();await win.setTitle('Catálogo — proyecto abierto');await win.maximize();Y hay funciones para obtener otra ventana por su etiqueta, o todas. Con dos advertencias:
- Cada operación es una llamada al puente, con su coste. Cambiar el título en cada pulsación de tecla son cientos de cruces por minuto. El nivel 21 mide ese coste.
- Todas necesitan permiso. Que la API exista en JavaScript no significa que esté concedida: si no hay capability que lo permita, la llamada se rechaza. Es el error del nivel 5.4.
Qué operación es de cuál
| operación | ventana | webview |
|---|---|---|
| tamaño, posición, minimizar, maximizar | ✓ | |
| título, decoraciones, siempre encima | ✓ | |
| pantalla completa, monitor actual | ✓ | |
| cargar una URL, recargar | ✓ | |
| abrir las herramientas de desarrollo | ✓ | |
| ejecutar JavaScript desde Rust | ✓ | |
| el nivel de zoom | ✓ | |
| cerrar | ✓ | ✓ |
La última fila es la que confunde: cerrar una webview y cerrar la ventana que la contiene son cosas distintas cuando hay varias. Con una sola, el tipo combinado hace lo esperado y no hay que pensarlo.