lib.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. //! Tauri is a framework for building tiny, blazing fast binaries for all major desktop platforms.
  5. //! Developers can integrate any front-end framework that compiles to HTML, JS and CSS for building their user interface.
  6. //! The backend of the application is a rust-sourced binary with an API that the front-end can interact with.
  7. //!
  8. //! # Cargo features
  9. //!
  10. //! The following are a list of [Cargo features](https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section) that can be enabled or disabled:
  11. //!
  12. //! - **wry** *(enabled by default)*: Enables the [wry](https://github.com/tauri-apps/wry) runtime. Only disable it if you want a custom runtime.
  13. //! - **isolation**: Enables the isolation pattern. Enabled by default if the `tauri > pattern > use` config option is set to `isolation` on the `tauri.conf.json` file.
  14. //! - **custom-protocol**: Feature managed by the Tauri CLI. When enabled, Tauri assumes a production environment instead of a development one.
  15. //! - **updater**: Enables the application auto updater. Enabled by default if the `updater` config is defined on the `tauri.conf.json` file.
  16. //! - **http-api**: Enables the [`api::http`] module.
  17. //! - **reqwest-client**: Uses `reqwest` as HTTP client on the `http` APIs. Improves performance, but increases the bundle size.
  18. //! - **command**: Enables the [`api::process::Command`] APIs.
  19. //! - **dialog**: Enables the [`api::dialog`] module.
  20. //! - **notification**: Enables the [`api::notification`] module.
  21. //! - **cli**: Enables usage of `clap` for CLI argument parsing. Enabled by default if the `cli` config is defined on the `tauri.conf.json` file.
  22. //! - **system-tray**: Enables application system tray API. Enabled by default if the `systemTray` config is defined on the `tauri.conf.json` file.
  23. //! - **macos-private-api**: Enables features only available in **macOS**'s private APIs, currently the `transparent` window functionality and the `fullScreenEnabled` preference setting to `true`. Enabled by default if the `tauri > macosPrivateApi` config flag is set to `true` on the `tauri.conf.json` file.
  24. //! - **window-data-url**: Enables usage of data URLs on the webview.
  25. //!
  26. //! ## Cargo allowlist features
  27. //!
  28. //! The following are a list of [Cargo features](https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section) that enables commands for Tauri's API package.
  29. //! These features are automatically enabled by the Tauri CLI based on the `allowlist` configuration under `tauri.conf.json`.
  30. //!
  31. //! - **api-all**: Enables all API endpoints.
  32. //!
  33. //! ### Clipboard allowlist
  34. //!
  35. //! - **clipboard-all**: Enables all [Clipboard APIs](https://tauri.studio/en/docs/api/js/modules/clipboard/).
  36. //! - **clipboard-read-text**: Enables the [`readText` API](https://tauri.studio/en/docs/api/js/modules/clipboard/#readtext).
  37. //! - **clipboard-write-text**: Enables the [`writeText` API](https://tauri.studio/en/docs/api/js/modules/clipboard/#writetext).
  38. //!
  39. //! ### Dialog allowlist
  40. //!
  41. //! - **dialog-all**: Enables all [Dialog APIs](https://tauri.studio/en/docs/api/js/modules/dialog).
  42. //! - **dialog-ask**: Enables the [`ask` API](https://tauri.studio/en/docs/api/js/modules/dialog#ask).
  43. //! - **dialog-confirm**: Enables the [`confirm` API](https://tauri.studio/en/docs/api/js/modules/dialog#confirm).
  44. //! - **dialog-message**: Enables the [`message` API](https://tauri.studio/en/docs/api/js/modules/dialog#message).
  45. //! - **dialog-open**: Enables the [`open` API](https://tauri.studio/en/docs/api/js/modules/dialog#open).
  46. //! - **dialog-save**: Enables the [`save` API](https://tauri.studio/en/docs/api/js/modules/dialog#save).
  47. //!
  48. //! ### Filesystem allowlist
  49. //!
  50. //! - **fs-all**: Enables all [Filesystem APIs](https://tauri.studio/en/docs/api/js/modules/fs).
  51. //! - **fs-copy-file**: Enables the [`copyFile` API](https://tauri.studio/en/docs/api/js/modules/fs#copyfile).
  52. //! - **fs-create-dir**: Enables the [`createDir` API](https://tauri.studio/en/docs/api/js/modules/fs#createdir).
  53. //! - **fs-read-dir**: Enables the [`readDir` API](https://tauri.studio/en/docs/api/js/modules/fs#readdir).
  54. //! - **fs-read-file**: Enables the [`readTextFile` API](https://tauri.studio/en/docs/api/js/modules/fs#readtextfile) and the [`readBinaryFile` API](https://tauri.studio/en/docs/api/js/modules/fs#readbinaryfile).
  55. //! - **fs-remove-dir**: Enables the [`removeDir` API](https://tauri.studio/en/docs/api/js/modules/fs#removedir).
  56. //! - **fs-remove-file**: Enables the [`removeFile` API](https://tauri.studio/en/docs/api/js/modules/fs#removefile).
  57. //! - **fs-rename-file**: Enables the [`renameFile` API](https://tauri.studio/en/docs/api/js/modules/fs#renamefile).
  58. //! - **fs-write-file**: Enables the [`writeFile` API](https://tauri.studio/en/docs/api/js/modules/fs#writefile) and the [`writeBinaryFile` API](https://tauri.studio/en/docs/api/js/modules/fs#writebinaryfile).
  59. //!
  60. //! ### Global shortcut allowlist
  61. //!
  62. //! - **global-shortcut-all**: Enables all [GlobalShortcut APIs](https://tauri.studio/en/docs/api/js/modules/globalShortcut).
  63. //!
  64. //! ### HTTP allowlist
  65. //!
  66. //! - **http-all**: Enables all [HTTP APIs](https://tauri.studio/en/docs/api/js/modules/http).
  67. //! - **http-request**: Enables the [`request` APIs](https://tauri.studio/en/docs/api/js/classes/http.client/).
  68. //!
  69. //! ### Notification allowlist
  70. //!
  71. //! - **notification-all**: Enables all [Notification APIs](https://tauri.studio/en/docs/api/js/modules/notification).
  72. //!
  73. //! ### OS allowlist
  74. //!
  75. //! - **os-all**: Enables all [OS APIs](https://tauri.studio/en/docs/api/js/modules/os).
  76. //!
  77. //! ### Path allowlist
  78. //!
  79. //! - **path-all**: Enables all [Path APIs](https://tauri.studio/en/docs/api/js/modules/path).
  80. //!
  81. //! ### Process allowlist
  82. //!
  83. //! - **process-all**: Enables all [Process APIs](https://tauri.studio/en/docs/api/js/modules/process).
  84. //! - **process-exit**: Enables the [`exit` API](https://tauri.studio/en/docs/api/js/modules/process#exit).
  85. //! - **process-relaunch**: Enables the [`relaunch` API](https://tauri.studio/en/docs/api/js/modules/process#relaunch).
  86. //!
  87. //! ### Protocol allowlist
  88. //!
  89. //! - **protocol-all**: Enables all Protocol APIs.
  90. //! - **protocol-asset**: Enables the `asset` custom protocol.
  91. //!
  92. //! ### Shell allowlist
  93. //!
  94. //! - **shell-all**: Enables all [Clipboard APIs](https://tauri.studio/en/docs/api/js/modules/shell).
  95. //! - **shell-execute**: Enables [executing arbitrary programs](https://tauri.studio/en/docs/api/js/classes/shell.Command#constructor).
  96. //! - **shell-sidecar**: Enables [executing a `sidecar` program](https://tauri.studio/en/docs/api/js/classes/shell.Command#sidecar).
  97. //! - **shell-open**: Enables the [`open` API](https://tauri.studio/en/docs/api/js/modules/shell#open).
  98. //!
  99. //! ### Window allowlist
  100. //!
  101. //! - **window-all**: Enables all [Window APIs](https://tauri.studio/en/docs/api/js/modules/window).
  102. //! - **window-create**: Enables the API used to [create new windows](https://tauri.studio/en/docs/api/js/classes/window.webviewwindow/).
  103. //! - **window-center**: Enables the [`center` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#center).
  104. //! - **window-request-user-attention**: Enables the [`requestUserAttention` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#requestuserattention).
  105. //! - **window-set-resizable**: Enables the [`setResizable` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setresizable).
  106. //! - **window-set-title**: Enables the [`setTitle` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#settitle).
  107. //! - **window-maximize**: Enables the [`maximize` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#maximize).
  108. //! - **window-unmaximize**: Enables the [`unmaximize` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#unmaximize).
  109. //! - **window-minimize**: Enables the [`minimize` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#minimize).
  110. //! - **window-unminimize**: Enables the [`unminimize` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#unminimize).
  111. //! - **window-show**: Enables the [`show` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#show).
  112. //! - **window-hide**: Enables the [`hide` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#hide).
  113. //! - **window-close**: Enables the [`close` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#close).
  114. //! - **window-set-decorations**: Enables the [`setDecorations` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setdecorations).
  115. //! - **window-set-always-on-top**: Enables the [`setAlwaysOnTop` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setalwaysontop).
  116. //! - **window-set-size**: Enables the [`setSize` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setsize).
  117. //! - **window-set-min-size**: Enables the [`setMinSize` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setminsize).
  118. //! - **window-set-max-size**: Enables the [`setMaxSize` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setmaxsize).
  119. //! - **window-set-position**: Enables the [`setPosition` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setposition).
  120. //! - **window-set-fullscreen**: Enables the [`setFullscreen` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setfullscreen).
  121. //! - **window-set-focus**: Enables the [`setFocus` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setfocus).
  122. //! - **window-set-icon**: Enables the [`setIcon` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#seticon).
  123. //! - **window-set-skip-taskbar**: Enables the [`setSkipTaskbar` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#setskiptaskbar).
  124. //! - **window-start-dragging**: Enables the [`startDragging` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#startdragging).
  125. //! - **window-print**: Enables the [`print` API](https://tauri.studio/en/docs/api/js/classes/window.WebviewWindow#print).
  126. #![warn(missing_docs, rust_2018_idioms)]
  127. #![cfg_attr(doc_cfg, feature(doc_cfg))]
  128. #[cfg(target_os = "macos")]
  129. #[doc(hidden)]
  130. pub use embed_plist;
  131. /// The Tauri error enum.
  132. pub use error::Error;
  133. #[cfg(feature = "shell-execute")]
  134. #[doc(hidden)]
  135. pub use regex;
  136. pub use tauri_macros::{command, generate_handler};
  137. pub mod api;
  138. pub(crate) mod app;
  139. pub mod async_runtime;
  140. pub mod command;
  141. /// The Tauri API endpoints.
  142. mod endpoints;
  143. mod error;
  144. mod event;
  145. mod hooks;
  146. mod manager;
  147. mod pattern;
  148. pub mod plugin;
  149. pub mod window;
  150. pub use tauri_runtime as runtime;
  151. /// The allowlist scopes.
  152. pub mod scope;
  153. pub mod settings;
  154. mod state;
  155. #[cfg(feature = "updater")]
  156. #[cfg_attr(doc_cfg, doc(cfg(feature = "updater")))]
  157. pub mod updater;
  158. pub use tauri_utils as utils;
  159. #[cfg(feature = "wry")]
  160. #[cfg_attr(doc_cfg, doc(cfg(feature = "wry")))]
  161. pub use tauri_runtime_wry::Wry;
  162. /// `Result<T, ::tauri::Error>`
  163. pub type Result<T> = std::result::Result<T, Error>;
  164. /// A task to run on the main thread.
  165. pub type SyncTask = Box<dyn FnOnce() + Send>;
  166. use crate::runtime::window::PendingWindow;
  167. use serde::Serialize;
  168. use std::{collections::HashMap, fmt, sync::Arc};
  169. // Export types likely to be used by the application.
  170. pub use runtime::http;
  171. #[cfg(target_os = "macos")]
  172. #[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
  173. pub use runtime::{menu::NativeImage, ActivationPolicy};
  174. #[cfg(feature = "system-tray")]
  175. #[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
  176. pub use {
  177. self::app::tray::{SystemTrayEvent, SystemTrayHandle},
  178. self::runtime::{
  179. menu::{SystemTrayMenu, SystemTrayMenuItem, SystemTraySubmenu},
  180. SystemTray,
  181. },
  182. };
  183. pub use {
  184. self::app::WindowMenuEvent,
  185. self::event::{Event, EventHandler},
  186. self::runtime::menu::{CustomMenuItem, Menu, MenuEntry, MenuItem, Submenu},
  187. self::window::menu::MenuEvent,
  188. };
  189. pub use {
  190. self::app::{
  191. App, AppHandle, AssetResolver, Builder, CloseRequestApi, GlobalWindowEvent, PathResolver,
  192. RunEvent,
  193. },
  194. self::hooks::{
  195. Invoke, InvokeError, InvokeHandler, InvokeMessage, InvokePayload, InvokeResolver,
  196. InvokeResponder, InvokeResponse, OnPageLoad, PageLoadPayload, SetupHook,
  197. },
  198. self::manager::Asset,
  199. self::runtime::{
  200. webview::{WebviewAttributes, WindowBuilder},
  201. window::{
  202. dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
  203. WindowEvent,
  204. },
  205. ClipboardManager, GlobalShortcutManager, Icon, RunIteration, Runtime, UserAttentionType,
  206. },
  207. self::state::{State, StateManager},
  208. self::utils::{
  209. assets::Assets,
  210. config::{Config, WindowUrl},
  211. Env, PackageInfo,
  212. },
  213. self::window::{Monitor, Window},
  214. scope::*,
  215. };
  216. /// Reads the config file at compile time and generates a [`Context`] based on its content.
  217. ///
  218. /// The default config file path is a `tauri.conf.json` file inside the Cargo manifest directory of
  219. /// the crate being built.
  220. ///
  221. /// # Custom Config Path
  222. ///
  223. /// You may pass a string literal to this macro to specify a custom path for the Tauri config file.
  224. /// If the path is relative, it will be search for relative to the Cargo manifest of the compiling
  225. /// crate.
  226. ///
  227. /// # Note
  228. ///
  229. /// This macro should not be called if you are using [`tauri-build`] to generate the context from
  230. /// inside your build script as it will just cause excess computations that will be discarded. Use
  231. /// either the [`tauri-build] method or this macro - not both.
  232. ///
  233. /// [`tauri-build`]: https://docs.rs/tauri-build
  234. pub use tauri_macros::generate_context;
  235. /// Include a [`Context`] that was generated by [`tauri-build`] inside your build script.
  236. ///
  237. /// You should either use [`tauri-build`] and this macro to include the compile time generated code,
  238. /// or [`generate_context!`]. Do not use both at the same time, as they generate the same code and
  239. /// will cause excess computations that will be discarded.
  240. ///
  241. /// [`tauri-build`]: https://docs.rs/tauri-build
  242. #[macro_export]
  243. macro_rules! tauri_build_context {
  244. () => {
  245. include!(concat!(env!("OUT_DIR"), "/tauri-build-context.rs"))
  246. };
  247. }
  248. pub use pattern::Pattern;
  249. /// User supplied data required inside of a Tauri application.
  250. ///
  251. /// # Stability
  252. /// This is the output of the [`generate_context`] macro, and is not considered part of the stable API.
  253. /// Unless you know what you are doing and are prepared for this type to have breaking changes, do not create it yourself.
  254. pub struct Context<A: Assets> {
  255. pub(crate) config: Config,
  256. pub(crate) assets: Arc<A>,
  257. pub(crate) default_window_icon: Option<Vec<u8>>,
  258. pub(crate) system_tray_icon: Option<Icon>,
  259. pub(crate) package_info: PackageInfo,
  260. pub(crate) _info_plist: (),
  261. pub(crate) pattern: Pattern,
  262. #[cfg(shell_scope)]
  263. pub(crate) shell_scope: scope::ShellScopeConfig,
  264. }
  265. impl<A: Assets> fmt::Debug for Context<A> {
  266. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  267. let mut d = f.debug_struct("Context");
  268. d.field("config", &self.config)
  269. .field("default_window_icon", &self.default_window_icon)
  270. .field("system_tray_icon", &self.system_tray_icon)
  271. .field("package_info", &self.package_info)
  272. .field("pattern", &self.pattern);
  273. #[cfg(shell_scope)]
  274. d.field("shell_scope", &self.shell_scope);
  275. d.finish()
  276. }
  277. }
  278. impl<A: Assets> Context<A> {
  279. /// The config the application was prepared with.
  280. #[inline(always)]
  281. pub fn config(&self) -> &Config {
  282. &self.config
  283. }
  284. /// A mutable reference to the config the application was prepared with.
  285. #[inline(always)]
  286. pub fn config_mut(&mut self) -> &mut Config {
  287. &mut self.config
  288. }
  289. /// The assets to be served directly by Tauri.
  290. #[inline(always)]
  291. pub fn assets(&self) -> Arc<A> {
  292. self.assets.clone()
  293. }
  294. /// A mutable reference to the assets to be served directly by Tauri.
  295. #[inline(always)]
  296. pub fn assets_mut(&mut self) -> &mut Arc<A> {
  297. &mut self.assets
  298. }
  299. /// The default window icon Tauri should use when creating windows.
  300. #[inline(always)]
  301. pub fn default_window_icon(&self) -> Option<&[u8]> {
  302. self.default_window_icon.as_deref()
  303. }
  304. /// A mutable reference to the default window icon Tauri should use when creating windows.
  305. #[inline(always)]
  306. pub fn default_window_icon_mut(&mut self) -> &mut Option<Vec<u8>> {
  307. &mut self.default_window_icon
  308. }
  309. /// The icon to use on the system tray UI.
  310. #[inline(always)]
  311. pub fn system_tray_icon(&self) -> Option<&Icon> {
  312. self.system_tray_icon.as_ref()
  313. }
  314. /// A mutable reference to the icon to use on the system tray UI.
  315. #[inline(always)]
  316. pub fn system_tray_icon_mut(&mut self) -> &mut Option<Icon> {
  317. &mut self.system_tray_icon
  318. }
  319. /// Package information.
  320. #[inline(always)]
  321. pub fn package_info(&self) -> &PackageInfo {
  322. &self.package_info
  323. }
  324. /// A mutable reference to the package information.
  325. #[inline(always)]
  326. pub fn package_info_mut(&mut self) -> &mut PackageInfo {
  327. &mut self.package_info
  328. }
  329. /// The application pattern.
  330. #[inline(always)]
  331. pub fn pattern(&self) -> &Pattern {
  332. &self.pattern
  333. }
  334. /// The scoped shell commands, where the `HashMap` key is the name each configuration.
  335. #[cfg(shell_scope)]
  336. #[inline(always)]
  337. pub fn allowed_commands(&self) -> &scope::ShellScopeConfig {
  338. &self.shell_scope
  339. }
  340. /// Create a new [`Context`] from the minimal required items.
  341. #[inline(always)]
  342. #[allow(clippy::too_many_arguments)]
  343. pub fn new(
  344. config: Config,
  345. assets: Arc<A>,
  346. default_window_icon: Option<Vec<u8>>,
  347. system_tray_icon: Option<Icon>,
  348. package_info: PackageInfo,
  349. info_plist: (),
  350. pattern: Pattern,
  351. #[cfg(shell_scope)] shell_scope: scope::ShellScopeConfig,
  352. ) -> Self {
  353. Self {
  354. config,
  355. assets,
  356. default_window_icon,
  357. system_tray_icon,
  358. package_info,
  359. _info_plist: info_plist,
  360. pattern,
  361. #[cfg(shell_scope)]
  362. shell_scope,
  363. }
  364. }
  365. }
  366. // TODO: expand these docs
  367. /// Manages a running application.
  368. pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
  369. /// The [`Config`] the manager was created with.
  370. fn config(&self) -> Arc<Config> {
  371. self.manager().config()
  372. }
  373. /// Emits a event to all windows.
  374. fn emit_all<S: Serialize + Clone>(&self, event: &str, payload: S) -> Result<()> {
  375. self.manager().emit_filter(event, payload, |_| true)
  376. }
  377. /// Emits an event to a window with the specified label.
  378. fn emit_to<S: Serialize + Clone>(&self, label: &str, event: &str, payload: S) -> Result<()> {
  379. self
  380. .manager()
  381. .emit_filter(event, payload, |w| label == w.label())
  382. }
  383. /// Listen to a global event.
  384. fn listen_global<F>(&self, event: impl Into<String>, handler: F) -> EventHandler
  385. where
  386. F: Fn(Event) + Send + 'static,
  387. {
  388. self.manager().listen(event.into(), None, handler)
  389. }
  390. /// Listen to a global event only once.
  391. fn once_global<F>(&self, event: impl Into<String>, handler: F) -> EventHandler
  392. where
  393. F: Fn(Event) + Send + 'static,
  394. {
  395. self.manager().once(event.into(), None, handler)
  396. }
  397. /// Trigger a global event.
  398. fn trigger_global(&self, event: &str, data: Option<String>) {
  399. self.manager().trigger(event, None, data)
  400. }
  401. /// Remove an event listener.
  402. fn unlisten(&self, handler_id: EventHandler) {
  403. self.manager().unlisten(handler_id)
  404. }
  405. /// Fetch a single window from the manager.
  406. fn get_window(&self, label: &str) -> Option<Window<R>> {
  407. self.manager().get_window(label)
  408. }
  409. /// Fetch all managed windows.
  410. fn windows(&self) -> HashMap<String, Window<R>> {
  411. self.manager().windows()
  412. }
  413. /// Add `state` to the state managed by the application.
  414. /// See [`crate::Builder#manage`] for instructions.
  415. fn manage<T>(&self, state: T)
  416. where
  417. T: Send + Sync + 'static,
  418. {
  419. self.manager().state().set(state);
  420. }
  421. /// Gets the managed state for the type `T`. Panics if the type is not managed.
  422. fn state<T>(&self) -> State<'_, T>
  423. where
  424. T: Send + Sync + 'static,
  425. {
  426. self
  427. .manager()
  428. .inner
  429. .state
  430. .try_get()
  431. .expect("state() called before manage() for given type")
  432. }
  433. /// Tries to get the managed state for the type `T`. Returns `None` if the type is not managed.
  434. fn try_state<T>(&self) -> Option<State<'_, T>>
  435. where
  436. T: Send + Sync + 'static,
  437. {
  438. self.manager().inner.state.try_get()
  439. }
  440. /// Gets the managed [`Env`].
  441. fn env(&self) -> Env {
  442. self.state::<Env>().inner().clone()
  443. }
  444. /// Gets the scope for the filesystem APIs.
  445. fn fs_scope(&self) -> FsScope {
  446. self.state::<Scopes>().inner().fs.clone()
  447. }
  448. /// Gets the scope for the asset protocol.
  449. #[cfg(protocol_asset)]
  450. fn asset_protocol_scope(&self) -> FsScope {
  451. self.state::<Scopes>().inner().asset_protocol.clone()
  452. }
  453. /// Gets the scope for the shell execute APIs.
  454. #[cfg(shell_scope)]
  455. fn shell_scope(&self) -> ShellScope {
  456. self.state::<Scopes>().inner().shell.clone()
  457. }
  458. }
  459. /// Prevent implementation details from leaking out of the [`Manager`] trait.
  460. pub(crate) mod sealed {
  461. use crate::{app::AppHandle, manager::WindowManager};
  462. use tauri_runtime::{Runtime, RuntimeHandle};
  463. /// A running [`Runtime`] or a dispatcher to it.
  464. pub enum RuntimeOrDispatch<'r, R: Runtime> {
  465. /// Reference to the running [`Runtime`].
  466. Runtime(&'r R),
  467. /// Handle to the running [`Runtime`].
  468. RuntimeHandle(R::Handle),
  469. /// A dispatcher to the running [`Runtime`].
  470. Dispatch(R::Dispatcher),
  471. }
  472. #[derive(Clone, serde::Serialize)]
  473. struct WindowCreatedEvent {
  474. label: String,
  475. }
  476. /// Managed handle to the application runtime.
  477. pub trait ManagerBase<R: Runtime> {
  478. /// The manager behind the [`Managed`] item.
  479. fn manager(&self) -> &WindowManager<R>;
  480. fn runtime(&self) -> RuntimeOrDispatch<'_, R>;
  481. fn app_handle(&self) -> AppHandle<R>;
  482. /// Creates a new [`Window`] on the [`Runtime`] and attaches it to the [`Manager`].
  483. fn create_new_window(
  484. &self,
  485. pending: crate::PendingWindow<R>,
  486. ) -> crate::Result<crate::Window<R>> {
  487. use crate::runtime::Dispatch;
  488. let labels = self.manager().labels().into_iter().collect::<Vec<_>>();
  489. let pending = self
  490. .manager()
  491. .prepare_window(self.app_handle(), pending, &labels)?;
  492. let window = match self.runtime() {
  493. RuntimeOrDispatch::Runtime(runtime) => runtime.create_window(pending),
  494. RuntimeOrDispatch::RuntimeHandle(handle) => handle.create_window(pending),
  495. RuntimeOrDispatch::Dispatch(mut dispatcher) => dispatcher.create_window(pending),
  496. }
  497. .map(|window| self.manager().attach_window(self.app_handle(), window))?;
  498. self.manager().emit_filter(
  499. "tauri://window-created",
  500. Some(WindowCreatedEvent {
  501. label: window.label().into(),
  502. }),
  503. |w| w != &window,
  504. )?;
  505. Ok(window)
  506. }
  507. }
  508. }
  509. /// Utilities for unit testing on Tauri applications.
  510. #[cfg(test)]
  511. pub mod test;
  512. #[cfg(test)]
  513. mod test_utils {
  514. use proptest::prelude::*;
  515. pub fn assert_send<T: Send>() {}
  516. pub fn assert_sync<T: Sync>() {}
  517. proptest! {
  518. #![proptest_config(ProptestConfig::with_cases(10000))]
  519. #[test]
  520. // check to see if spawn executes a function.
  521. fn check_spawn_task(task in "[a-z]+") {
  522. // create dummy task function
  523. let dummy_task = async move {
  524. format!("{}-run-dummy-task", task);
  525. };
  526. // call spawn
  527. crate::async_runtime::spawn(dummy_task);
  528. }
  529. }
  530. }