tauri-apps/tauri
Event system
The event system is the loose-coupling counterpart to commands. Where a command is a request/response pair tied to a single function, an event is fire-and-forget broadcast that any number of listeners can subscribe to. Both Rust and JS sit on the same bus.
Concepts
- Event — a name (string) plus a
serde-serialisable payload. - Listener — a callback registered with
listen(Rust or JS) that receives every matching event. - Target — global, a specific webview, a webview-window, or a window. Restricting target makes broadcasts scoped.
- One-shot —
oncelisteners auto-unsubscribe after the first delivery.
Surfaces
From JS
import { listen, emit, once } from '@tauri-apps/api/event';
const unlisten = await listen<MyPayload>('user-logged-in', (event) => { … });
await emit('refresh');
await once('updater://download-finished', () => { … });
unlisten();The JS API lives in packages/api/src/event.ts.
From Rust
use tauri::{Manager, AppHandle};
app_handle.emit("refresh", ())?;
let id = app_handle.listen_any("user-logged-in", |evt| { … });
app_handle.unlisten(id);The Manager trait exposes emit, emit_to, listen_any, listen, unlisten, once. Webview and WebviewWindow carry scoped variants (Webview::emit, etc.).
Flow
graph LR
JSemit["JS emit('e', p)"] -->|"command plugin:event|emit"| RustBus["AppManager event bus"]
RustBus -->|"deliver to JS subscribers"| JSlisteners["JS listen handlers"]
RustBus --> RustListeners["Rust listen_any handlers"]
RustEmit["Rust emit('e', p)"] --> RustBusInternally, JS-emitted events are normal IPC messages routed through plugin:event|emit. The Rust manager dedupes, applies any target filter, and fans out to:
- Native Rust listeners registered via
listen_any/listen. - WebView-side listeners registered via
listen(the manager callswebview.eval(format!("__TAURI__.event.dispatch(...)"))).
crates/tauri/src/event/ holds the bus implementation, listener bookkeeping, and the message types. ACL gates this through the core:event:default permission and friends in crates/tauri/permissions/event/.
Built-in events
A handful of events are emitted by the runtime:
| Event | When |
|---|---|
tauri://close-requested |
A close request arrived for a window. |
tauri://destroyed |
A webview was destroyed. |
tauri://focus / blur |
Focus changes. |
tauri://drop / drag-over |
OS-native drag-and-drop into the webview. |
tauri://resize / move |
Window geometry changes. |
tauri://theme-changed |
OS theme switch. |
tauri://scale-change |
DPI change. |
tauri://menu |
Menu activations (when wired to events). |
tauri://update-* |
Updater plugin events (in tauri-plugin-updater). |
Plugins commonly emit their own events under their own prefix (e.g. download-progress from a download plugin).
Files at a glance
| File | Role |
|---|---|
crates/tauri/src/event/ |
Rust bus, listener registry, EventName types |
crates/tauri/permissions/event/ |
Built-in ACL permissions for emit/listen |
crates/tauri/src/manager/mod.rs |
Hosts the global listener table |
packages/api/src/event.ts |
JS-side listen/emit/once and Event type |
Cross-references
- The command path used by JS-emitted events: systems/ipc-and-commands.
- Permission setup for events: systems/acl-and-capabilities.
- Plugin lifecycle that often produces events: systems/plugin-system.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.