lib.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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 as EmittedEvent, EventHandler},
  55. runtime::window::PendingWindow,
  56. };
  57. use serde::Serialize;
  58. use std::{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, CloseRequestApi, Event, GlobalWindowEvent, PathResolver},
  76. self::hooks::{
  77. Invoke, InvokeError, InvokeHandler, InvokeMessage, InvokeResolver, InvokeResponse, OnPageLoad,
  78. PageLoadPayload, SetupHook,
  79. },
  80. self::runtime::{
  81. webview::{WebviewAttributes, WindowBuilder},
  82. window::{
  83. dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
  84. WindowEvent,
  85. },
  86. Icon, RunIteration, Runtime, UserAttentionType,
  87. },
  88. self::state::{State, StateManager},
  89. self::window::{Monitor, Window},
  90. };
  91. #[cfg(feature = "system-tray")]
  92. #[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
  93. pub use {
  94. self::app::tray::{SystemTrayEvent, SystemTrayHandle},
  95. self::runtime::{
  96. menu::{SystemTrayMenu, SystemTrayMenuItem, SystemTraySubmenu},
  97. SystemTray,
  98. },
  99. };
  100. #[cfg(feature = "menu")]
  101. #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))]
  102. pub use {
  103. self::app::WindowMenuEvent,
  104. self::runtime::menu::{Menu, MenuItem, Submenu},
  105. self::window::menu::MenuEvent,
  106. };
  107. /// Reads the config file at compile time and generates a [`Context`] based on its content.
  108. ///
  109. /// The default config file path is a `tauri.conf.json` file inside the Cargo manifest directory of
  110. /// the crate being built.
  111. ///
  112. /// # Custom Config Path
  113. ///
  114. /// You may pass a string literal to this macro to specify a custom path for the Tauri config file.
  115. /// If the path is relative, it will be search for relative to the Cargo manifest of the compiling
  116. /// crate.
  117. ///
  118. /// # Note
  119. ///
  120. /// This macro should not be called if you are using [`tauri-build`] to generate the context from
  121. /// inside your build script as it will just cause excess computations that will be discarded. Use
  122. /// either the [`tauri-build] method or this macro - not both.
  123. ///
  124. /// [`tauri-build`]: https://docs.rs/tauri-build
  125. pub use tauri_macros::generate_context;
  126. /// Include a [`Context`] that was generated by [`tauri-build`] inside your build script.
  127. ///
  128. /// You should either use [`tauri-build`] and this macro to include the compile time generated code,
  129. /// or [`generate_context!`]. Do not use both at the same time, as they generate the same code and
  130. /// will cause excess computations that will be discarded.
  131. ///
  132. /// [`tauri-build`]: https://docs.rs/tauri-build
  133. #[macro_export]
  134. macro_rules! tauri_build_context {
  135. () => {
  136. include!(concat!(env!("OUT_DIR"), "/tauri-build-context.rs"))
  137. };
  138. }
  139. /// User supplied data required inside of a Tauri application.
  140. ///
  141. /// # Stability
  142. /// This is the output of the `tauri::generate_context!` macro, and is not considered part of the stable API.
  143. /// Unless you know what you are doing and are prepared for this type to have breaking changes, do not create it yourself.
  144. pub struct Context<A: Assets> {
  145. pub(crate) config: Config,
  146. pub(crate) assets: Arc<A>,
  147. pub(crate) default_window_icon: Option<Vec<u8>>,
  148. pub(crate) system_tray_icon: Option<Icon>,
  149. pub(crate) package_info: crate::api::PackageInfo,
  150. }
  151. impl<A: Assets> Context<A> {
  152. /// The config the application was prepared with.
  153. #[inline(always)]
  154. pub fn config(&self) -> &Config {
  155. &self.config
  156. }
  157. /// A mutable reference to the config the application was prepared with.
  158. #[inline(always)]
  159. pub fn config_mut(&mut self) -> &mut Config {
  160. &mut self.config
  161. }
  162. /// The assets to be served directly by Tauri.
  163. #[inline(always)]
  164. pub fn assets(&self) -> Arc<A> {
  165. self.assets.clone()
  166. }
  167. /// A mutable reference to the assets to be served directly by Tauri.
  168. #[inline(always)]
  169. pub fn assets_mut(&mut self) -> &mut Arc<A> {
  170. &mut self.assets
  171. }
  172. /// The default window icon Tauri should use when creating windows.
  173. #[inline(always)]
  174. pub fn default_window_icon(&self) -> Option<&[u8]> {
  175. self.default_window_icon.as_deref()
  176. }
  177. /// A mutable reference to the default window icon Tauri should use when creating windows.
  178. #[inline(always)]
  179. pub fn default_window_icon_mut(&mut self) -> &mut Option<Vec<u8>> {
  180. &mut self.default_window_icon
  181. }
  182. /// The icon to use on the system tray UI.
  183. #[inline(always)]
  184. pub fn system_tray_icon(&self) -> Option<&Icon> {
  185. self.system_tray_icon.as_ref()
  186. }
  187. /// A mutable reference to the icon to use on the system tray UI.
  188. #[inline(always)]
  189. pub fn system_tray_icon_mut(&mut self) -> &mut Option<Icon> {
  190. &mut self.system_tray_icon
  191. }
  192. /// Package information.
  193. #[inline(always)]
  194. pub fn package_info(&self) -> &crate::api::PackageInfo {
  195. &self.package_info
  196. }
  197. /// A mutable reference to the package information.
  198. #[inline(always)]
  199. pub fn package_info_mut(&mut self) -> &mut crate::api::PackageInfo {
  200. &mut self.package_info
  201. }
  202. /// Create a new [`Context`] from the minimal required items.
  203. #[inline(always)]
  204. pub fn new(
  205. config: Config,
  206. assets: Arc<A>,
  207. default_window_icon: Option<Vec<u8>>,
  208. system_tray_icon: Option<Icon>,
  209. package_info: crate::api::PackageInfo,
  210. ) -> Self {
  211. Self {
  212. config,
  213. assets,
  214. default_window_icon,
  215. system_tray_icon,
  216. package_info,
  217. }
  218. }
  219. }
  220. // TODO: expand these docs
  221. /// Manages a running application.
  222. pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
  223. /// The [`Config`] the manager was created with.
  224. fn config(&self) -> Arc<Config> {
  225. self.manager().config()
  226. }
  227. /// Emits a event to all windows.
  228. fn emit_all<S: Serialize + Clone>(&self, event: &str, payload: S) -> Result<()> {
  229. self.manager().emit_filter(event, payload, |_| true)
  230. }
  231. /// Emits an event to a window with the specified label.
  232. fn emit_to<S: Serialize + Clone>(&self, label: &str, event: &str, payload: S) -> Result<()> {
  233. self
  234. .manager()
  235. .emit_filter(event, payload, |w| label == w.label())
  236. }
  237. /// Listen to a global event.
  238. fn listen_global<F>(&self, event: impl Into<String>, handler: F) -> EventHandler
  239. where
  240. F: Fn(EmittedEvent) + Send + 'static,
  241. {
  242. self.manager().listen(event.into(), None, handler)
  243. }
  244. /// Listen to a global event only once.
  245. fn once_global<F>(&self, event: impl Into<String>, handler: F) -> EventHandler
  246. where
  247. F: Fn(EmittedEvent) + Send + 'static,
  248. {
  249. self.manager().once(event.into(), None, handler)
  250. }
  251. /// Trigger a global event.
  252. fn trigger_global(&self, event: &str, data: Option<String>) {
  253. self.manager().trigger(event, None, data)
  254. }
  255. /// Remove an event listener.
  256. fn unlisten(&self, handler_id: EventHandler) {
  257. self.manager().unlisten(handler_id)
  258. }
  259. /// Fetch a single window from the manager.
  260. fn get_window(&self, label: &str) -> Option<Window<R>> {
  261. self.manager().get_window(label)
  262. }
  263. /// Fetch all managed windows.
  264. fn windows(&self) -> HashMap<String, Window<R>> {
  265. self.manager().windows()
  266. }
  267. /// Add `state` to the state managed by the application.
  268. /// See [`crate::Builder#manage`] for instructions.
  269. fn manage<T>(&self, state: T)
  270. where
  271. T: Send + Sync + 'static,
  272. {
  273. self.manager().state().set(state);
  274. }
  275. /// Gets the managed state for the type `T`.
  276. fn state<T>(&self) -> State<'_, T>
  277. where
  278. T: Send + Sync + 'static,
  279. {
  280. self.manager().inner.state.get()
  281. }
  282. }
  283. /// Prevent implementation details from leaking out of the [`Manager`] trait.
  284. pub(crate) mod sealed {
  285. use crate::{app::AppHandle, manager::WindowManager};
  286. use tauri_runtime::{Runtime, RuntimeHandle};
  287. /// A running [`Runtime`] or a dispatcher to it.
  288. pub enum RuntimeOrDispatch<'r, R: Runtime> {
  289. /// Reference to the running [`Runtime`].
  290. Runtime(&'r R),
  291. /// Handle to the running [`Runtime`].
  292. RuntimeHandle(R::Handle),
  293. /// A dispatcher to the running [`Runtime`].
  294. Dispatch(R::Dispatcher),
  295. }
  296. /// Managed handle to the application runtime.
  297. pub trait ManagerBase<R: Runtime> {
  298. /// The manager behind the [`Managed`] item.
  299. fn manager(&self) -> &WindowManager<R>;
  300. fn runtime(&self) -> RuntimeOrDispatch<'_, R>;
  301. fn app_handle(&self) -> AppHandle<R>;
  302. /// Creates a new [`Window`] on the [`Runtime`] and attaches it to the [`Manager`].
  303. fn create_new_window(
  304. &self,
  305. pending: crate::PendingWindow<R>,
  306. ) -> crate::Result<crate::Window<R>> {
  307. use crate::runtime::Dispatch;
  308. let labels = self.manager().labels().into_iter().collect::<Vec<_>>();
  309. let pending = self
  310. .manager()
  311. .prepare_window(self.app_handle(), pending, &labels)?;
  312. match self.runtime() {
  313. RuntimeOrDispatch::Runtime(runtime) => runtime.create_window(pending).map_err(Into::into),
  314. RuntimeOrDispatch::RuntimeHandle(handle) => {
  315. handle.create_window(pending).map_err(Into::into)
  316. }
  317. RuntimeOrDispatch::Dispatch(mut dispatcher) => {
  318. dispatcher.create_window(pending).map_err(Into::into)
  319. }
  320. }
  321. .map(|window| self.manager().attach_window(self.app_handle(), window))
  322. }
  323. }
  324. }
  325. #[cfg(test)]
  326. mod test {
  327. use proptest::prelude::*;
  328. proptest! {
  329. #![proptest_config(ProptestConfig::with_cases(10000))]
  330. #[test]
  331. // check to see if spawn executes a function.
  332. fn check_spawn_task(task in "[a-z]+") {
  333. // create dummy task function
  334. let dummy_task = async move {
  335. format!("{}-run-dummy-task", task);
  336. };
  337. // call spawn
  338. crate::async_runtime::spawn(dummy_task);
  339. }
  340. }
  341. }