window.rs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use super::{InvokeContext, InvokeResponse};
  5. #[cfg(window_create)]
  6. use crate::runtime::{webview::WindowBuilder, Dispatch};
  7. use crate::{
  8. runtime::{
  9. window::dpi::{Position, Size},
  10. Runtime, UserAttentionType,
  11. },
  12. utils::config::WindowConfig,
  13. Manager,
  14. };
  15. use serde::Deserialize;
  16. use tauri_macros::{module_command_handler, CommandModule};
  17. use crate::runtime::Icon;
  18. use std::path::PathBuf;
  19. #[derive(Deserialize)]
  20. #[serde(untagged)]
  21. pub enum IconDto {
  22. File(PathBuf),
  23. Raw(Vec<u8>),
  24. }
  25. impl From<IconDto> for Icon {
  26. fn from(icon: IconDto) -> Self {
  27. match icon {
  28. IconDto::File(path) => Self::File(path),
  29. IconDto::Raw(raw) => Self::Raw(raw),
  30. }
  31. }
  32. }
  33. /// Window management API descriptor.
  34. #[derive(Deserialize)]
  35. #[serde(tag = "type", content = "payload", rename_all = "camelCase")]
  36. pub enum WindowManagerCmd {
  37. // Getters
  38. ScaleFactor,
  39. InnerPosition,
  40. OuterPosition,
  41. InnerSize,
  42. OuterSize,
  43. IsFullscreen,
  44. IsMaximized,
  45. IsDecorated,
  46. IsResizable,
  47. IsVisible,
  48. CurrentMonitor,
  49. PrimaryMonitor,
  50. AvailableMonitors,
  51. // Setters
  52. Center,
  53. RequestUserAttention(Option<UserAttentionType>),
  54. SetResizable(bool),
  55. SetTitle(String),
  56. Maximize,
  57. Unmaximize,
  58. ToggleMaximize,
  59. Minimize,
  60. Unminimize,
  61. Show,
  62. Hide,
  63. Close,
  64. SetDecorations(bool),
  65. #[serde(rename_all = "camelCase")]
  66. SetAlwaysOnTop(bool),
  67. SetSize(Size),
  68. SetMinSize(Option<Size>),
  69. SetMaxSize(Option<Size>),
  70. SetPosition(Position),
  71. SetFullscreen(bool),
  72. SetFocus,
  73. SetIcon {
  74. icon: IconDto,
  75. },
  76. SetSkipTaskbar(bool),
  77. StartDragging,
  78. Print,
  79. // internals
  80. #[serde(rename = "__toggleMaximize")]
  81. InternalToggleMaximize,
  82. }
  83. impl WindowManagerCmd {
  84. fn into_allowlist_error(self) -> crate::Error {
  85. match self {
  86. Self::Center => crate::Error::ApiNotAllowlisted("window > center".to_string()),
  87. Self::RequestUserAttention(_) => {
  88. crate::Error::ApiNotAllowlisted("window > requestUserAttention".to_string())
  89. }
  90. Self::SetResizable(_) => crate::Error::ApiNotAllowlisted("window > setResizable".to_string()),
  91. Self::SetTitle(_) => crate::Error::ApiNotAllowlisted("window > setTitle".to_string()),
  92. Self::Maximize => crate::Error::ApiNotAllowlisted("window > maximize".to_string()),
  93. Self::Unmaximize => crate::Error::ApiNotAllowlisted("window > unmaximize".to_string()),
  94. Self::ToggleMaximize => {
  95. crate::Error::ApiNotAllowlisted("window > maximize and window > unmaximize".to_string())
  96. }
  97. Self::Minimize => crate::Error::ApiNotAllowlisted("window > minimize".to_string()),
  98. Self::Unminimize => crate::Error::ApiNotAllowlisted("window > unminimize".to_string()),
  99. Self::Show => crate::Error::ApiNotAllowlisted("window > show".to_string()),
  100. Self::Hide => crate::Error::ApiNotAllowlisted("window > hide".to_string()),
  101. Self::Close => crate::Error::ApiNotAllowlisted("window > close".to_string()),
  102. Self::SetDecorations(_) => {
  103. crate::Error::ApiNotAllowlisted("window > setDecorations".to_string())
  104. }
  105. Self::SetAlwaysOnTop(_) => {
  106. crate::Error::ApiNotAllowlisted("window > setAlwaysOnTop".to_string())
  107. }
  108. Self::SetSize(_) => crate::Error::ApiNotAllowlisted("window > setSize".to_string()),
  109. Self::SetMinSize(_) => crate::Error::ApiNotAllowlisted("window > setMinSize".to_string()),
  110. Self::SetMaxSize(_) => crate::Error::ApiNotAllowlisted("window > setMaxSize".to_string()),
  111. Self::SetPosition(_) => crate::Error::ApiNotAllowlisted("window > setPosition".to_string()),
  112. Self::SetFullscreen(_) => {
  113. crate::Error::ApiNotAllowlisted("window > setFullscreen".to_string())
  114. }
  115. Self::SetIcon { .. } => crate::Error::ApiNotAllowlisted("window > setIcon".to_string()),
  116. Self::SetSkipTaskbar(_) => {
  117. crate::Error::ApiNotAllowlisted("window > setSkipTaskbar".to_string())
  118. }
  119. Self::StartDragging => crate::Error::ApiNotAllowlisted("window > startDragging".to_string()),
  120. Self::Print => crate::Error::ApiNotAllowlisted("window > print".to_string()),
  121. Self::InternalToggleMaximize => {
  122. crate::Error::ApiNotAllowlisted("window > maximize and window > unmaximize".to_string())
  123. }
  124. _ => crate::Error::ApiNotAllowlisted("window > all".to_string()),
  125. }
  126. }
  127. }
  128. /// The API descriptor.
  129. #[derive(Deserialize, CommandModule)]
  130. #[cmd(async)]
  131. #[serde(tag = "cmd", content = "data", rename_all = "camelCase")]
  132. pub enum Cmd {
  133. CreateWebview {
  134. options: Box<WindowConfig>,
  135. },
  136. Manage {
  137. label: Option<String>,
  138. cmd: WindowManagerCmd,
  139. },
  140. }
  141. impl Cmd {
  142. #[module_command_handler(window_create, "window > create")]
  143. async fn create_webview<R: Runtime>(
  144. context: InvokeContext<R>,
  145. options: Box<WindowConfig>,
  146. ) -> crate::Result<()> {
  147. let mut window = context.window;
  148. let label = options.label.clone();
  149. let url = options.url.clone();
  150. window.create_window(label, url, |_, webview_attributes| {
  151. (
  152. <<R::Dispatcher as Dispatch>::WindowBuilder>::with_config(*options),
  153. webview_attributes,
  154. )
  155. })?;
  156. Ok(())
  157. }
  158. async fn manage<R: Runtime>(
  159. context: InvokeContext<R>,
  160. label: Option<String>,
  161. cmd: WindowManagerCmd,
  162. ) -> crate::Result<InvokeResponse> {
  163. let window = match label {
  164. Some(l) if !l.is_empty() => context
  165. .window
  166. .get_window(&l)
  167. .ok_or(crate::Error::WebviewNotFound)?,
  168. _ => context.window,
  169. };
  170. match cmd {
  171. // Getters
  172. WindowManagerCmd::ScaleFactor => return Ok(window.scale_factor()?.into()),
  173. WindowManagerCmd::InnerPosition => return Ok(window.inner_position()?.into()),
  174. WindowManagerCmd::OuterPosition => return Ok(window.outer_position()?.into()),
  175. WindowManagerCmd::InnerSize => return Ok(window.inner_size()?.into()),
  176. WindowManagerCmd::OuterSize => return Ok(window.outer_size()?.into()),
  177. WindowManagerCmd::IsFullscreen => return Ok(window.is_fullscreen()?.into()),
  178. WindowManagerCmd::IsMaximized => return Ok(window.is_maximized()?.into()),
  179. WindowManagerCmd::IsDecorated => return Ok(window.is_decorated()?.into()),
  180. WindowManagerCmd::IsResizable => return Ok(window.is_resizable()?.into()),
  181. WindowManagerCmd::IsVisible => return Ok(window.is_visible()?.into()),
  182. WindowManagerCmd::CurrentMonitor => return Ok(window.current_monitor()?.into()),
  183. WindowManagerCmd::PrimaryMonitor => return Ok(window.primary_monitor()?.into()),
  184. WindowManagerCmd::AvailableMonitors => return Ok(window.available_monitors()?.into()),
  185. // Setters
  186. #[cfg(window_center)]
  187. WindowManagerCmd::Center => window.center()?,
  188. #[cfg(window_request_user_attention)]
  189. WindowManagerCmd::RequestUserAttention(request_type) => {
  190. window.request_user_attention(request_type)?
  191. }
  192. #[cfg(window_set_resizable)]
  193. WindowManagerCmd::SetResizable(resizable) => window.set_resizable(resizable)?,
  194. #[cfg(window_set_title)]
  195. WindowManagerCmd::SetTitle(title) => window.set_title(&title)?,
  196. #[cfg(window_maximize)]
  197. WindowManagerCmd::Maximize => window.maximize()?,
  198. #[cfg(window_unmaximize)]
  199. WindowManagerCmd::Unmaximize => window.unmaximize()?,
  200. #[cfg(all(window_maximize, window_unmaximize))]
  201. WindowManagerCmd::ToggleMaximize => match window.is_maximized()? {
  202. true => window.unmaximize()?,
  203. false => window.maximize()?,
  204. },
  205. #[cfg(window_minimize)]
  206. WindowManagerCmd::Minimize => window.minimize()?,
  207. #[cfg(window_unminimize)]
  208. WindowManagerCmd::Unminimize => window.unminimize()?,
  209. #[cfg(window_show)]
  210. WindowManagerCmd::Show => window.show()?,
  211. #[cfg(window_hide)]
  212. WindowManagerCmd::Hide => window.hide()?,
  213. #[cfg(window_close)]
  214. WindowManagerCmd::Close => window.close()?,
  215. #[cfg(window_set_decorations)]
  216. WindowManagerCmd::SetDecorations(decorations) => window.set_decorations(decorations)?,
  217. #[cfg(window_set_always_on_top)]
  218. WindowManagerCmd::SetAlwaysOnTop(always_on_top) => window.set_always_on_top(always_on_top)?,
  219. #[cfg(window_set_size)]
  220. WindowManagerCmd::SetSize(size) => window.set_size(size)?,
  221. #[cfg(window_set_min_size)]
  222. WindowManagerCmd::SetMinSize(size) => window.set_min_size(size)?,
  223. #[cfg(window_set_max_size)]
  224. WindowManagerCmd::SetMaxSize(size) => window.set_max_size(size)?,
  225. #[cfg(window_set_position)]
  226. WindowManagerCmd::SetPosition(position) => window.set_position(position)?,
  227. #[cfg(window_set_fullscreen)]
  228. WindowManagerCmd::SetFullscreen(fullscreen) => window.set_fullscreen(fullscreen)?,
  229. #[cfg(window_set_focus)]
  230. WindowManagerCmd::SetFocus => window.set_focus()?,
  231. #[cfg(window_set_icon)]
  232. WindowManagerCmd::SetIcon { icon } => window.set_icon(icon.into())?,
  233. #[cfg(window_set_skip_taskbar)]
  234. WindowManagerCmd::SetSkipTaskbar(skip) => window.set_skip_taskbar(skip)?,
  235. #[cfg(window_start_dragging)]
  236. WindowManagerCmd::StartDragging => window.start_dragging()?,
  237. #[cfg(window_print)]
  238. WindowManagerCmd::Print => window.print()?,
  239. // internals
  240. #[cfg(all(window_maximize, window_unmaximize))]
  241. WindowManagerCmd::InternalToggleMaximize => {
  242. if window.is_resizable()? {
  243. match window.is_maximized()? {
  244. true => window.unmaximize()?,
  245. false => window.maximize()?,
  246. }
  247. }
  248. }
  249. #[allow(unreachable_patterns)]
  250. _ => return Err(cmd.into_allowlist_error()),
  251. }
  252. #[allow(unreachable_code)]
  253. Ok(().into())
  254. }
  255. }