lib.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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 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. //! - **menu**: Enables application menus support.
  14. //! - **reqwest-client**: Uses `reqwest` as HTTP client on the `http` APIs. Improves performance, but increases the bundle size.
  15. //! - **cli**: Enables usage of `clap` for CLI argument parsing. Enabled by default if the `cli` config is defined on the `tauri.conf.json` file.
  16. //! - **system-tray**: Enables application system tray API. Enabled by default if the `systemTray` config is defined on the `tauri.conf.json` file.
  17. //! - **updater**: Enables the application auto updater. Enabled by default if the `updater` config is defined on the `tauri.conf.json` file.
  18. #![allow(
  19. // Clippy bug: https://github.com/rust-lang/rust-clippy/issues/7422
  20. clippy::nonstandard_macro_braces,
  21. )]
  22. #![warn(missing_docs, rust_2018_idioms)]
  23. #![cfg_attr(doc_cfg, feature(doc_cfg))]
  24. /// The Tauri error enum.
  25. pub use error::Error;
  26. pub use tauri_macros::{command, generate_handler};
  27. pub mod api;
  28. pub(crate) mod app;
  29. /// Async runtime.
  30. pub mod async_runtime;
  31. pub mod command;
  32. /// The Tauri API endpoints.
  33. mod endpoints;
  34. mod error;
  35. mod event;
  36. mod hooks;
  37. mod manager;
  38. pub mod plugin;
  39. /// Tauri window.
  40. pub mod window;
  41. use tauri_runtime as runtime;
  42. /// The Tauri-specific settings for your runtime e.g. notification permission status.
  43. pub mod settings;
  44. mod state;
  45. #[cfg(feature = "updater")]
  46. pub mod updater;
  47. #[cfg(feature = "wry")]
  48. pub use tauri_runtime_wry::Wry;
  49. /// `Result<T, ::tauri::Error>`
  50. pub type Result<T> = std::result::Result<T, Error>;
  51. /// A task to run on the main thread.
  52. pub type SyncTask = Box<dyn FnOnce() + Send>;
  53. use crate::{
  54. event::{Event, EventHandler},
  55. runtime::window::PendingWindow,
  56. };
  57. use serde::Serialize;
  58. use std::{borrow::Borrow, collections::HashMap, sync::Arc};
  59. // Export types likely to be used by the application.
  60. #[cfg(any(feature = "menu", feature = "system-tray"))]
  61. #[cfg_attr(doc_cfg, doc(cfg(any(feature = "menu", feature = "system-tray"))))]
  62. pub use runtime::menu::CustomMenuItem;
  63. #[cfg(all(target_os = "macos", any(feature = "menu", feature = "system-tray")))]
  64. #[cfg_attr(
  65. doc_cfg,
  66. doc(cfg(all(target_os = "macos", any(feature = "menu", feature = "system-tray"))))
  67. )]
  68. pub use runtime::menu::NativeImage;
  69. pub use {
  70. self::api::assets::Assets,
  71. self::api::{
  72. config::{Config, WindowUrl},
  73. PackageInfo,
  74. },
  75. self::app::{App, AppHandle, Builder, GlobalWindowEvent},
  76. self::hooks::{
  77. Invoke, InvokeError, InvokeHandler, InvokeMessage, InvokeResolver, InvokeResponse, OnPageLoad,
  78. PageLoadPayload, SetupHook,
  79. },
  80. self::runtime::{
  81. tag::{Tag, TagRef},
  82. webview::{WebviewAttributes, WindowBuilder},
  83. window::{
  84. dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
  85. WindowEvent,
  86. },
  87. Icon, MenuId, Params, RunIteration, UserAttentionType,
  88. },
  89. self::state::{State, StateManager},
  90. self::window::{Monitor, Window},
  91. };
  92. #[cfg(feature = "system-tray")]
  93. #[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
  94. pub use {
  95. self::app::tray::SystemTrayEvent,
  96. self::runtime::{
  97. menu::{SystemTrayMenu, SystemTrayMenuItem, SystemTraySubmenu},
  98. SystemTray,
  99. },
  100. };
  101. #[cfg(feature = "menu")]
  102. #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))]
  103. pub use {
  104. self::app::WindowMenuEvent,
  105. self::runtime::menu::{Menu, MenuItem, Submenu},
  106. self::window::menu::MenuEvent,
  107. };
  108. /// Reads the config file at compile time and generates a [`Context`] based on its content.
  109. ///
  110. /// The default config file path is a `tauri.conf.json` file inside the Cargo manifest directory of
  111. /// the crate being built.
  112. ///
  113. /// # Custom Config Path
  114. ///
  115. /// You may pass a string literal to this macro to specify a custom path for the Tauri config file.
  116. /// If the path is relative, it will be search for relative to the Cargo manifest of the compiling
  117. /// crate.
  118. ///
  119. /// # Note
  120. ///
  121. /// This macro should not be called if you are using [`tauri-build`] to generate the context from
  122. /// inside your build script as it will just cause excess computations that will be discarded. Use
  123. /// either the [`tauri-build] method or this macro - not both.
  124. ///
  125. /// [`tauri-build`]: https://docs.rs/tauri-build
  126. pub use tauri_macros::generate_context;
  127. /// Include a [`Context`] that was generated by [`tauri-build`] inside your build script.
  128. ///
  129. /// You should either use [`tauri-build`] and this macro to include the compile time generated code,
  130. /// or [`generate_context!`]. Do not use both at the same time, as they generate the same code and
  131. /// will cause excess computations that will be discarded.
  132. ///
  133. /// [`tauri-build`]: https://docs.rs/tauri-build
  134. #[macro_export]
  135. macro_rules! tauri_build_context {
  136. () => {
  137. include!(concat!(env!("OUT_DIR"), "/tauri-build-context.rs"))
  138. };
  139. }
  140. /// User supplied data required inside of a Tauri application.
  141. ///
  142. /// # Stability
  143. /// This is the output of the `tauri::generate_context!` macro, and is not considered part of the stable API.
  144. /// Unless you know what you are doing and are prepared for this type to have breaking changes, do not create it yourself.
  145. pub struct Context<A: Assets> {
  146. pub(crate) config: Config,
  147. pub(crate) assets: Arc<A>,
  148. pub(crate) default_window_icon: Option<Vec<u8>>,
  149. pub(crate) system_tray_icon: Option<Icon>,
  150. pub(crate) package_info: crate::api::PackageInfo,
  151. }
  152. impl<A: Assets> Context<A> {
  153. /// The config the application was prepared with.
  154. #[inline(always)]
  155. pub fn config(&self) -> &Config {
  156. &self.config
  157. }
  158. /// A mutable reference to the config the application was prepared with.
  159. #[inline(always)]
  160. pub fn config_mut(&mut self) -> &mut Config {
  161. &mut self.config
  162. }
  163. /// The assets to be served directly by Tauri.
  164. #[inline(always)]
  165. pub fn assets(&self) -> Arc<A> {
  166. self.assets.clone()
  167. }
  168. /// A mutable reference to the assets to be served directly by Tauri.
  169. #[inline(always)]
  170. pub fn assets_mut(&mut self) -> &mut Arc<A> {
  171. &mut self.assets
  172. }
  173. /// The default window icon Tauri should use when creating windows.
  174. #[inline(always)]
  175. pub fn default_window_icon(&self) -> Option<&[u8]> {
  176. self.default_window_icon.as_deref()
  177. }
  178. /// A mutable reference to the default window icon Tauri should use when creating windows.
  179. #[inline(always)]
  180. pub fn default_window_icon_mut(&mut self) -> &mut Option<Vec<u8>> {
  181. &mut self.default_window_icon
  182. }
  183. /// The icon to use on the system tray UI.
  184. #[inline(always)]
  185. pub fn system_tray_icon(&self) -> Option<&Icon> {
  186. self.system_tray_icon.as_ref()
  187. }
  188. /// A mutable reference to the icon to use on the system tray UI.
  189. #[inline(always)]
  190. pub fn system_tray_icon_mut(&mut self) -> &mut Option<Icon> {
  191. &mut self.system_tray_icon
  192. }
  193. /// Package information.
  194. #[inline(always)]
  195. pub fn package_info(&self) -> &crate::api::PackageInfo {
  196. &self.package_info
  197. }
  198. /// A mutable reference to the package information.
  199. #[inline(always)]
  200. pub fn package_info_mut(&mut self) -> &mut crate::api::PackageInfo {
  201. &mut self.package_info
  202. }
  203. /// Create a new [`Context`] from the minimal required items.
  204. #[inline(always)]
  205. pub fn new(
  206. config: Config,
  207. assets: Arc<A>,
  208. default_window_icon: Option<Vec<u8>>,
  209. system_tray_icon: Option<Icon>,
  210. package_info: crate::api::PackageInfo,
  211. ) -> Self {
  212. Self {
  213. config,
  214. assets,
  215. default_window_icon,
  216. system_tray_icon,
  217. package_info,
  218. }
  219. }
  220. }
  221. // TODO: expand these docs
  222. /// Manages a running application.
  223. pub trait Manager<P: Params>: sealed::ManagerBase<P> {
  224. /// The [`Config`] the manager was created with.
  225. fn config(&self) -> Arc<Config> {
  226. self.manager().config()
  227. }
  228. /// Emits a event to all windows.
  229. fn emit_all<E: ?Sized, S>(&self, event: &E, payload: S) -> Result<()>
  230. where
  231. P::Event: Borrow<E>,
  232. E: TagRef<P::Event>,
  233. S: Serialize + Clone,
  234. {
  235. self.manager().emit_filter(event, payload, |_| true)
  236. }
  237. /// Emits an event to a window with the specified label.
  238. fn emit_to<E: ?Sized, L: ?Sized, S: Serialize + Clone>(
  239. &self,
  240. label: &L,
  241. event: &E,
  242. payload: S,
  243. ) -> Result<()>
  244. where
  245. P::Label: Borrow<L>,
  246. P::Event: Borrow<E>,
  247. L: TagRef<P::Label>,
  248. E: TagRef<P::Event>,
  249. {
  250. self
  251. .manager()
  252. .emit_filter(event, payload, |w| label == w.label())
  253. }
  254. /// Listen to a global event.
  255. fn listen_global<E: Into<P::Event>, F>(&self, event: E, handler: F) -> EventHandler
  256. where
  257. F: Fn(Event) + Send + 'static,
  258. {
  259. self.manager().listen(event.into(), None, handler)
  260. }
  261. /// Listen to a global event only once.
  262. fn once_global<E: Into<P::Event>, F>(&self, event: E, handler: F) -> EventHandler
  263. where
  264. F: Fn(Event) + Send + 'static,
  265. {
  266. self.manager().once(event.into(), None, handler)
  267. }
  268. /// Trigger a global event.
  269. fn trigger_global<E: ?Sized>(&self, event: &E, data: Option<String>)
  270. where
  271. P::Event: Borrow<E>,
  272. E: TagRef<P::Event>,
  273. {
  274. self.manager().trigger(event, None, data)
  275. }
  276. /// Remove an event listener.
  277. fn unlisten(&self, handler_id: EventHandler) {
  278. self.manager().unlisten(handler_id)
  279. }
  280. /// Fetch a single window from the manager.
  281. fn get_window<L: ?Sized>(&self, label: &L) -> Option<Window<P>>
  282. where
  283. P::Label: Borrow<L>,
  284. L: TagRef<P::Label>,
  285. {
  286. self.manager().get_window(label)
  287. }
  288. /// Fetch all managed windows.
  289. fn windows(&self) -> HashMap<P::Label, Window<P>> {
  290. self.manager().windows()
  291. }
  292. /// Add `state` to the state managed by the application.
  293. /// See [`crate::Builder#manage`] for instructions.
  294. fn manage<T>(&self, state: T)
  295. where
  296. T: Send + Sync + 'static,
  297. {
  298. self.manager().state().set(state);
  299. }
  300. /// Gets the managed state for the type `T`.
  301. fn state<T>(&self) -> State<'_, T>
  302. where
  303. T: Send + Sync + 'static,
  304. {
  305. self.manager().inner.state.get()
  306. }
  307. }
  308. /// Prevent implementation details from leaking out of the [`Manager`] trait.
  309. pub(crate) mod sealed {
  310. use crate::{app::AppHandle, manager::WindowManager};
  311. use tauri_runtime::{Params, Runtime, RuntimeHandle};
  312. /// A running [`Runtime`] or a dispatcher to it.
  313. pub enum RuntimeOrDispatch<'r, P: Params> {
  314. /// Reference to the running [`Runtime`].
  315. Runtime(&'r P::Runtime),
  316. /// Handle to the running [`Runtime`].
  317. RuntimeHandle(<P::Runtime as Runtime>::Handle),
  318. /// A dispatcher to the running [`Runtime`].
  319. Dispatch(<P::Runtime as Runtime>::Dispatcher),
  320. }
  321. /// Managed handle to the application runtime.
  322. pub trait ManagerBase<P: Params> {
  323. /// The manager behind the [`Managed`] item.
  324. fn manager(&self) -> &WindowManager<P>;
  325. fn runtime(&self) -> RuntimeOrDispatch<'_, P>;
  326. fn app_handle(&self) -> AppHandle<P>;
  327. /// Creates a new [`Window`] on the [`Runtime`] and attaches it to the [`Manager`].
  328. fn create_new_window(
  329. &self,
  330. pending: crate::PendingWindow<P>,
  331. ) -> crate::Result<crate::Window<P>> {
  332. use crate::runtime::Dispatch;
  333. let labels = self.manager().labels().into_iter().collect::<Vec<_>>();
  334. let pending = self
  335. .manager()
  336. .prepare_window(self.app_handle(), pending, &labels)?;
  337. match self.runtime() {
  338. RuntimeOrDispatch::Runtime(runtime) => runtime.create_window(pending).map_err(Into::into),
  339. RuntimeOrDispatch::RuntimeHandle(handle) => {
  340. handle.create_window(pending).map_err(Into::into)
  341. }
  342. RuntimeOrDispatch::Dispatch(mut dispatcher) => {
  343. dispatcher.create_window(pending).map_err(Into::into)
  344. }
  345. }
  346. .map(|window| self.manager().attach_window(self.app_handle(), window))
  347. }
  348. }
  349. }
  350. #[cfg(test)]
  351. mod test {
  352. use proptest::prelude::*;
  353. proptest! {
  354. #![proptest_config(ProptestConfig::with_cases(10000))]
  355. #[test]
  356. // check to see if spawn executes a function.
  357. fn check_spawn_task(task in "[a-z]+") {
  358. // create dummy task function
  359. let dummy_task = async move {
  360. format!("{}-run-dummy-task", task);
  361. };
  362. // call spawn
  363. crate::async_runtime::spawn(dummy_task);
  364. }
  365. }
  366. }