lib.rs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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. //! The user interface in Tauri apps currently leverages Cocoa/WebKit on macOS, gtk-webkit2 on Linux and MSHTML (IE10/11) or Webkit via Edge on Windows.
  9. //! Tauri uses (and contributes to) the MIT licensed project that you can find at [webview](https://github.com/webview/webview).
  10. #![warn(missing_docs, rust_2018_idioms)]
  11. #![cfg_attr(doc_cfg, feature(doc_cfg))]
  12. /// The Tauri error enum.
  13. pub use error::Error;
  14. pub use tauri_macros::{command, generate_handler};
  15. pub mod api;
  16. pub(crate) mod app;
  17. /// Async runtime.
  18. pub mod async_runtime;
  19. pub mod command;
  20. /// The Tauri API endpoints.
  21. mod endpoints;
  22. mod error;
  23. mod event;
  24. mod hooks;
  25. mod manager;
  26. pub mod plugin;
  27. /// Tauri window.
  28. pub mod window;
  29. use tauri_runtime as runtime;
  30. /// The Tauri-specific settings for your runtime e.g. notification permission status.
  31. pub mod settings;
  32. mod state;
  33. #[cfg(feature = "updater")]
  34. pub mod updater;
  35. #[cfg(feature = "wry")]
  36. pub use tauri_runtime_wry::Wry;
  37. /// `Result<T, ::tauri::Error>`
  38. pub type Result<T> = std::result::Result<T, Error>;
  39. /// A task to run on the main thread.
  40. pub type SyncTask = Box<dyn FnOnce() + Send>;
  41. use crate::{
  42. event::{Event, EventHandler},
  43. runtime::window::PendingWindow,
  44. };
  45. use serde::Serialize;
  46. use std::{borrow::Borrow, collections::HashMap, sync::Arc};
  47. // Export types likely to be used by the application.
  48. #[cfg(any(feature = "menu", feature = "system-tray"))]
  49. #[cfg_attr(doc_cfg, doc(cfg(any(feature = "menu", feature = "system-tray"))))]
  50. pub use runtime::menu::CustomMenuItem;
  51. pub use {
  52. self::api::assets::Assets,
  53. self::api::{
  54. config::{Config, WindowUrl},
  55. PackageInfo,
  56. },
  57. self::app::{App, Builder, GlobalWindowEvent},
  58. self::hooks::{
  59. Invoke, InvokeError, InvokeHandler, InvokeMessage, InvokeResolver, InvokeResponse, OnPageLoad,
  60. PageLoadPayload, SetupHook,
  61. },
  62. self::runtime::{
  63. tag::{Tag, TagRef},
  64. webview::{WebviewAttributes, WindowBuilder},
  65. window::{
  66. dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Pixel, Position, Size},
  67. WindowEvent,
  68. },
  69. MenuId, Params,
  70. },
  71. self::state::{State, StateManager},
  72. self::window::{Monitor, Window},
  73. };
  74. #[cfg(feature = "system-tray")]
  75. #[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
  76. pub use {self::app::SystemTrayEvent, self::runtime::menu::SystemTrayMenuItem};
  77. #[cfg(feature = "menu")]
  78. #[cfg_attr(doc_cfg, doc(cfg(feature = "menu")))]
  79. pub use {
  80. self::app::WindowMenuEvent,
  81. self::runtime::menu::{Menu, MenuItem},
  82. self::window::MenuEvent,
  83. };
  84. /// Reads the config file at compile time and generates a [`Context`] based on its content.
  85. ///
  86. /// The default config file path is a `tauri.conf.json` file inside the Cargo manifest directory of
  87. /// the crate being built.
  88. ///
  89. /// # Custom Config Path
  90. ///
  91. /// You may pass a string literal to this macro to specify a custom path for the Tauri config file.
  92. /// If the path is relative, it will be search for relative to the Cargo manifest of the compiling
  93. /// crate.
  94. ///
  95. /// # Note
  96. ///
  97. /// This macro should not be called if you are using [`tauri-build`] to generate the context from
  98. /// inside your build script as it will just cause excess computations that will be discarded. Use
  99. /// either the [`tauri-build] method or this macro - not both.
  100. ///
  101. /// [`tauri-build`]: https://docs.rs/tauri-build
  102. pub use tauri_macros::generate_context;
  103. /// Include a [`Context`] that was generated by [`tauri-build`] inside your build script.
  104. ///
  105. /// You should either use [`tauri-build`] and this macro to include the compile time generated code,
  106. /// or [`generate_context!`]. Do not use both at the same time, as they generate the same code and
  107. /// will cause excess computations that will be discarded.
  108. ///
  109. /// [`tauri-build`]: https://docs.rs/tauri-build
  110. #[macro_export]
  111. macro_rules! tauri_build_context {
  112. () => {
  113. include!(concat!(env!("OUT_DIR"), "/tauri-build-context.rs"))
  114. };
  115. }
  116. /// User supplied data required inside of a Tauri application.
  117. pub struct Context<A: Assets> {
  118. /// The config the application was prepared with.
  119. pub config: Config,
  120. /// The assets to be served directly by Tauri.
  121. pub assets: Arc<A>,
  122. /// The default window icon Tauri should use when creating windows.
  123. pub default_window_icon: Option<Vec<u8>>,
  124. /// The icon to use use on the system tray UI.
  125. #[cfg(target_os = "linux")]
  126. pub system_tray_icon: Option<std::path::PathBuf>,
  127. /// The icon to use use on the system tray UI.
  128. #[cfg(not(target_os = "linux"))]
  129. pub system_tray_icon: Option<Vec<u8>>,
  130. /// Package information.
  131. pub package_info: crate::api::PackageInfo,
  132. }
  133. /// Manages a running application.
  134. ///
  135. /// TODO: expand these docs
  136. pub trait Manager<P: Params>: sealed::ManagerBase<P> {
  137. /// The [`Config`] the manager was created with.
  138. fn config(&self) -> Arc<Config> {
  139. self.manager().config()
  140. }
  141. /// Emits a event to all windows.
  142. fn emit_all<E: ?Sized, S>(&self, event: &E, payload: S) -> Result<()>
  143. where
  144. P::Event: Borrow<E>,
  145. E: TagRef<P::Event>,
  146. S: Serialize + Clone,
  147. {
  148. self.manager().emit_filter(event, payload, |_| true)
  149. }
  150. /// Emits an event to a window with the specified label.
  151. fn emit_to<E: ?Sized, L: ?Sized, S: Serialize + Clone>(
  152. &self,
  153. label: &L,
  154. event: &E,
  155. payload: S,
  156. ) -> Result<()>
  157. where
  158. P::Label: Borrow<L>,
  159. P::Event: Borrow<E>,
  160. L: TagRef<P::Label>,
  161. E: TagRef<P::Event>,
  162. {
  163. self
  164. .manager()
  165. .emit_filter(event, payload, |w| label == w.label())
  166. }
  167. /// Listen to a global event.
  168. fn listen_global<E: Into<P::Event>, F>(&self, event: E, handler: F) -> EventHandler
  169. where
  170. F: Fn(Event) + Send + 'static,
  171. {
  172. self.manager().listen(event.into(), None, handler)
  173. }
  174. /// Listen to a global event only once.
  175. fn once_global<E: Into<P::Event>, F>(&self, event: E, handler: F) -> EventHandler
  176. where
  177. F: Fn(Event) + Send + 'static,
  178. {
  179. self.manager().once(event.into(), None, handler)
  180. }
  181. /// Trigger a global event.
  182. fn trigger_global<E: ?Sized>(&self, event: &E, data: Option<String>)
  183. where
  184. P::Event: Borrow<E>,
  185. E: TagRef<P::Event>,
  186. {
  187. self.manager().trigger(event, None, data)
  188. }
  189. /// Remove an event listener.
  190. fn unlisten(&self, handler_id: EventHandler) {
  191. self.manager().unlisten(handler_id)
  192. }
  193. /// Fetch a single window from the manager.
  194. fn get_window<L: ?Sized>(&self, label: &L) -> Option<Window<P>>
  195. where
  196. P::Label: Borrow<L>,
  197. L: TagRef<P::Label>,
  198. {
  199. self.manager().get_window(label)
  200. }
  201. /// Fetch all managed windows.
  202. fn windows(&self) -> HashMap<P::Label, Window<P>> {
  203. self.manager().windows()
  204. }
  205. /// Add `state` to the state managed by the application.
  206. /// See [`crate::Builder#manage`] for instructions.
  207. fn manage<T>(&self, state: T)
  208. where
  209. T: Send + Sync + 'static,
  210. {
  211. self.manager().state().set(state);
  212. }
  213. /// Gets the managed state for the type `T`.
  214. fn state<T>(&self) -> State<'_, T>
  215. where
  216. T: Send + Sync + 'static,
  217. {
  218. self.manager().inner.state.get()
  219. }
  220. }
  221. /// Prevent implementation details from leaking out of the [`Manager`] trait.
  222. pub(crate) mod sealed {
  223. use crate::manager::WindowManager;
  224. use tauri_runtime::{Params, Runtime};
  225. /// A running [`Runtime`] or a dispatcher to it.
  226. pub enum RuntimeOrDispatch<'r, P: Params> {
  227. /// Reference to the running [`Runtime`].
  228. Runtime(&'r P::Runtime),
  229. /// A dispatcher to the running [`Runtime`].
  230. Dispatch(<P::Runtime as Runtime>::Dispatcher),
  231. }
  232. /// Managed handle to the application runtime.
  233. pub trait ManagerBase<P: Params> {
  234. /// The manager behind the [`Managed`] item.
  235. fn manager(&self) -> &WindowManager<P>;
  236. /// Creates a new [`Window`] on the [`Runtime`] and attaches it to the [`Manager`].
  237. fn create_new_window(
  238. &self,
  239. runtime: RuntimeOrDispatch<'_, P>,
  240. pending: crate::PendingWindow<P>,
  241. ) -> crate::Result<crate::Window<P>> {
  242. use crate::runtime::Dispatch;
  243. let labels = self.manager().labels().into_iter().collect::<Vec<_>>();
  244. let pending = self.manager().prepare_window(pending, &labels)?;
  245. match runtime {
  246. RuntimeOrDispatch::Runtime(runtime) => runtime.create_window(pending).map_err(Into::into),
  247. RuntimeOrDispatch::Dispatch(mut dispatcher) => {
  248. dispatcher.create_window(pending).map_err(Into::into)
  249. }
  250. }
  251. .map(|window| self.manager().attach_window(window))
  252. }
  253. }
  254. }
  255. #[cfg(test)]
  256. mod test {
  257. use proptest::prelude::*;
  258. proptest! {
  259. #![proptest_config(ProptestConfig::with_cases(10000))]
  260. #[test]
  261. // check to see if spawn executes a function.
  262. fn check_spawn_task(task in "[a-z]+") {
  263. // create dummy task function
  264. let dummy_task = async move {
  265. format!("{}-run-dummy-task", task);
  266. };
  267. // call spawn
  268. crate::async_runtime::spawn(dummy_task);
  269. }
  270. }
  271. }