mock_runtime.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. // Copyright 2019-2022 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. #![allow(dead_code)]
  5. use tauri_runtime::{
  6. menu::{Menu, MenuUpdate},
  7. monitor::Monitor,
  8. webview::{WindowBuilder, WindowBuilderBase},
  9. window::{
  10. dpi::{PhysicalPosition, PhysicalSize, Position, Size},
  11. CursorIcon, DetachedWindow, MenuEvent, PendingWindow, WindowEvent,
  12. },
  13. Dispatch, EventLoopProxy, Icon, Result, RunEvent, Runtime, RuntimeHandle, UserAttentionType,
  14. UserEvent,
  15. };
  16. #[cfg(all(desktop, feature = "system-tray"))]
  17. use tauri_runtime::{
  18. menu::{SystemTrayMenu, TrayHandle},
  19. SystemTray, SystemTrayEvent, TrayId,
  20. };
  21. #[cfg(target_os = "macos")]
  22. use tauri_utils::TitleBarStyle;
  23. use tauri_utils::{config::WindowConfig, Theme};
  24. use uuid::Uuid;
  25. #[cfg(windows)]
  26. use windows::Win32::Foundation::HWND;
  27. use std::{
  28. collections::HashMap,
  29. fmt,
  30. sync::{Arc, Mutex},
  31. };
  32. type ShortcutMap = HashMap<String, Box<dyn Fn() + Send + 'static>>;
  33. #[derive(Clone)]
  34. pub struct RuntimeContext {
  35. shortcuts: Arc<Mutex<ShortcutMap>>,
  36. clipboard: Arc<Mutex<Option<String>>>,
  37. }
  38. impl fmt::Debug for RuntimeContext {
  39. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  40. f.debug_struct("RuntimeContext")
  41. .field("clipboard", &self.clipboard)
  42. .finish()
  43. }
  44. }
  45. #[derive(Debug, Clone)]
  46. pub struct MockRuntimeHandle {
  47. context: RuntimeContext,
  48. }
  49. impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
  50. type Runtime = MockRuntime;
  51. fn create_proxy(&self) -> EventProxy {
  52. unimplemented!()
  53. }
  54. /// Create a new webview window.
  55. fn create_window(
  56. &self,
  57. pending: PendingWindow<T, Self::Runtime>,
  58. ) -> Result<DetachedWindow<T, Self::Runtime>> {
  59. Ok(DetachedWindow {
  60. label: pending.label,
  61. dispatcher: MockDispatcher {
  62. context: self.context.clone(),
  63. },
  64. menu_ids: Default::default(),
  65. js_event_listeners: Default::default(),
  66. })
  67. }
  68. /// Run a task on the main thread.
  69. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  70. unimplemented!()
  71. }
  72. #[cfg(all(desktop, feature = "system-tray"))]
  73. #[cfg_attr(doc_cfg, doc(cfg(all(desktop, feature = "system-tray"))))]
  74. fn system_tray(
  75. &self,
  76. system_tray: SystemTray,
  77. ) -> Result<<Self::Runtime as Runtime<T>>::TrayHandler> {
  78. unimplemented!()
  79. }
  80. fn raw_display_handle(&self) -> raw_window_handle::RawDisplayHandle {
  81. unimplemented!()
  82. }
  83. }
  84. #[derive(Debug, Clone)]
  85. pub struct MockDispatcher {
  86. context: RuntimeContext,
  87. }
  88. #[cfg(all(desktop, feature = "global-shortcut"))]
  89. #[derive(Debug, Clone)]
  90. pub struct MockGlobalShortcutManager {
  91. context: RuntimeContext,
  92. }
  93. #[cfg(all(desktop, feature = "global-shortcut"))]
  94. impl tauri_runtime::GlobalShortcutManager for MockGlobalShortcutManager {
  95. fn is_registered(&self, accelerator: &str) -> Result<bool> {
  96. Ok(
  97. self
  98. .context
  99. .shortcuts
  100. .lock()
  101. .unwrap()
  102. .contains_key(accelerator),
  103. )
  104. }
  105. fn register<F: Fn() + Send + 'static>(&mut self, accelerator: &str, handler: F) -> Result<()> {
  106. self
  107. .context
  108. .shortcuts
  109. .lock()
  110. .unwrap()
  111. .insert(accelerator.into(), Box::new(handler));
  112. Ok(())
  113. }
  114. fn unregister_all(&mut self) -> Result<()> {
  115. *self.context.shortcuts.lock().unwrap() = Default::default();
  116. Ok(())
  117. }
  118. fn unregister(&mut self, accelerator: &str) -> Result<()> {
  119. self.context.shortcuts.lock().unwrap().remove(accelerator);
  120. Ok(())
  121. }
  122. }
  123. #[cfg(feature = "clipboard")]
  124. #[derive(Debug, Clone)]
  125. pub struct MockClipboardManager {
  126. context: RuntimeContext,
  127. }
  128. #[cfg(feature = "clipboard")]
  129. impl tauri_runtime::ClipboardManager for MockClipboardManager {
  130. fn write_text<T: Into<String>>(&mut self, text: T) -> Result<()> {
  131. self.context.clipboard.lock().unwrap().replace(text.into());
  132. Ok(())
  133. }
  134. fn read_text(&self) -> Result<Option<String>> {
  135. Ok(self.context.clipboard.lock().unwrap().clone())
  136. }
  137. }
  138. #[derive(Debug, Clone)]
  139. pub struct MockWindowBuilder {}
  140. impl WindowBuilderBase for MockWindowBuilder {}
  141. impl WindowBuilder for MockWindowBuilder {
  142. fn new() -> Self {
  143. Self {}
  144. }
  145. fn with_config(config: WindowConfig) -> Self {
  146. Self {}
  147. }
  148. fn menu(self, menu: Menu) -> Self {
  149. self
  150. }
  151. fn center(self) -> Self {
  152. self
  153. }
  154. fn position(self, x: f64, y: f64) -> Self {
  155. self
  156. }
  157. fn inner_size(self, min_width: f64, min_height: f64) -> Self {
  158. self
  159. }
  160. fn min_inner_size(self, min_width: f64, min_height: f64) -> Self {
  161. self
  162. }
  163. fn max_inner_size(self, max_width: f64, max_height: f64) -> Self {
  164. self
  165. }
  166. fn resizable(self, resizable: bool) -> Self {
  167. self
  168. }
  169. fn title<S: Into<String>>(self, title: S) -> Self {
  170. self
  171. }
  172. fn fullscreen(self, fullscreen: bool) -> Self {
  173. self
  174. }
  175. fn focus(self) -> Self {
  176. self
  177. }
  178. fn maximized(self, maximized: bool) -> Self {
  179. self
  180. }
  181. fn visible(self, visible: bool) -> Self {
  182. self
  183. }
  184. #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))]
  185. #[cfg_attr(
  186. doc_cfg,
  187. doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api")))
  188. )]
  189. fn transparent(self, transparent: bool) -> Self {
  190. self
  191. }
  192. fn decorations(self, decorations: bool) -> Self {
  193. self
  194. }
  195. fn always_on_top(self, always_on_top: bool) -> Self {
  196. self
  197. }
  198. fn icon(self, icon: Icon) -> Result<Self> {
  199. Ok(self)
  200. }
  201. fn skip_taskbar(self, skip: bool) -> Self {
  202. self
  203. }
  204. #[cfg(windows)]
  205. fn parent_window(self, parent: HWND) -> Self {
  206. self
  207. }
  208. #[cfg(target_os = "macos")]
  209. fn parent_window(self, parent: *mut std::ffi::c_void) -> Self {
  210. self
  211. }
  212. #[cfg(windows)]
  213. fn owner_window(self, owner: HWND) -> Self {
  214. self
  215. }
  216. #[cfg(target_os = "macos")]
  217. fn title_bar_style(self, style: TitleBarStyle) -> Self {
  218. self
  219. }
  220. #[cfg(target_os = "macos")]
  221. fn hidden_title(self, transparent: bool) -> Self {
  222. self
  223. }
  224. fn theme(self, theme: Option<Theme>) -> Self {
  225. self
  226. }
  227. fn has_icon(&self) -> bool {
  228. false
  229. }
  230. fn get_menu(&self) -> Option<&Menu> {
  231. None
  232. }
  233. }
  234. impl<T: UserEvent> Dispatch<T> for MockDispatcher {
  235. type Runtime = MockRuntime;
  236. type WindowBuilder = MockWindowBuilder;
  237. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  238. Ok(())
  239. }
  240. fn on_window_event<F: Fn(&WindowEvent) + Send + 'static>(&self, f: F) -> Uuid {
  241. Uuid::new_v4()
  242. }
  243. fn on_menu_event<F: Fn(&MenuEvent) + Send + 'static>(&self, f: F) -> Uuid {
  244. Uuid::new_v4()
  245. }
  246. #[cfg(any(debug_assertions, feature = "devtools"))]
  247. fn open_devtools(&self) {}
  248. #[cfg(any(debug_assertions, feature = "devtools"))]
  249. fn close_devtools(&self) {}
  250. #[cfg(any(debug_assertions, feature = "devtools"))]
  251. fn is_devtools_open(&self) -> Result<bool> {
  252. Ok(false)
  253. }
  254. fn scale_factor(&self) -> Result<f64> {
  255. Ok(1.0)
  256. }
  257. fn inner_position(&self) -> Result<PhysicalPosition<i32>> {
  258. Ok(PhysicalPosition { x: 0, y: 0 })
  259. }
  260. fn outer_position(&self) -> Result<PhysicalPosition<i32>> {
  261. Ok(PhysicalPosition { x: 0, y: 0 })
  262. }
  263. fn inner_size(&self) -> Result<PhysicalSize<u32>> {
  264. Ok(PhysicalSize {
  265. width: 0,
  266. height: 0,
  267. })
  268. }
  269. fn outer_size(&self) -> Result<PhysicalSize<u32>> {
  270. Ok(PhysicalSize {
  271. width: 0,
  272. height: 0,
  273. })
  274. }
  275. fn is_fullscreen(&self) -> Result<bool> {
  276. Ok(false)
  277. }
  278. fn is_maximized(&self) -> Result<bool> {
  279. Ok(false)
  280. }
  281. fn is_decorated(&self) -> Result<bool> {
  282. Ok(false)
  283. }
  284. fn is_resizable(&self) -> Result<bool> {
  285. Ok(false)
  286. }
  287. fn is_visible(&self) -> Result<bool> {
  288. Ok(true)
  289. }
  290. fn is_menu_visible(&self) -> Result<bool> {
  291. Ok(true)
  292. }
  293. fn current_monitor(&self) -> Result<Option<Monitor>> {
  294. Ok(None)
  295. }
  296. fn primary_monitor(&self) -> Result<Option<Monitor>> {
  297. Ok(None)
  298. }
  299. fn available_monitors(&self) -> Result<Vec<Monitor>> {
  300. Ok(Vec::new())
  301. }
  302. fn theme(&self) -> Result<Theme> {
  303. Ok(Theme::Light)
  304. }
  305. #[cfg(any(
  306. target_os = "linux",
  307. target_os = "dragonfly",
  308. target_os = "freebsd",
  309. target_os = "netbsd",
  310. target_os = "openbsd"
  311. ))]
  312. fn gtk_window(&self) -> Result<gtk::ApplicationWindow> {
  313. unimplemented!()
  314. }
  315. fn raw_window_handle(&self) -> Result<raw_window_handle::RawWindowHandle> {
  316. unimplemented!()
  317. }
  318. fn center(&self) -> Result<()> {
  319. Ok(())
  320. }
  321. fn print(&self) -> Result<()> {
  322. Ok(())
  323. }
  324. fn request_user_attention(&self, request_type: Option<UserAttentionType>) -> Result<()> {
  325. Ok(())
  326. }
  327. fn create_window(
  328. &mut self,
  329. pending: PendingWindow<T, Self::Runtime>,
  330. ) -> Result<DetachedWindow<T, Self::Runtime>> {
  331. unimplemented!()
  332. }
  333. fn set_resizable(&self, resizable: bool) -> Result<()> {
  334. Ok(())
  335. }
  336. fn set_title<S: Into<String>>(&self, title: S) -> Result<()> {
  337. Ok(())
  338. }
  339. fn maximize(&self) -> Result<()> {
  340. Ok(())
  341. }
  342. fn unmaximize(&self) -> Result<()> {
  343. Ok(())
  344. }
  345. fn minimize(&self) -> Result<()> {
  346. Ok(())
  347. }
  348. fn unminimize(&self) -> Result<()> {
  349. Ok(())
  350. }
  351. fn show_menu(&self) -> Result<()> {
  352. Ok(())
  353. }
  354. fn hide_menu(&self) -> Result<()> {
  355. Ok(())
  356. }
  357. fn show(&self) -> Result<()> {
  358. Ok(())
  359. }
  360. fn hide(&self) -> Result<()> {
  361. Ok(())
  362. }
  363. fn close(&self) -> Result<()> {
  364. Ok(())
  365. }
  366. fn set_decorations(&self, decorations: bool) -> Result<()> {
  367. Ok(())
  368. }
  369. fn set_always_on_top(&self, always_on_top: bool) -> Result<()> {
  370. Ok(())
  371. }
  372. fn set_size(&self, size: Size) -> Result<()> {
  373. Ok(())
  374. }
  375. fn set_min_size(&self, size: Option<Size>) -> Result<()> {
  376. Ok(())
  377. }
  378. fn set_max_size(&self, size: Option<Size>) -> Result<()> {
  379. Ok(())
  380. }
  381. fn set_position(&self, position: Position) -> Result<()> {
  382. Ok(())
  383. }
  384. fn set_fullscreen(&self, fullscreen: bool) -> Result<()> {
  385. Ok(())
  386. }
  387. fn set_focus(&self) -> Result<()> {
  388. Ok(())
  389. }
  390. fn set_icon(&self, icon: Icon) -> Result<()> {
  391. Ok(())
  392. }
  393. fn set_skip_taskbar(&self, skip: bool) -> Result<()> {
  394. Ok(())
  395. }
  396. fn set_cursor_grab(&self, grab: bool) -> Result<()> {
  397. Ok(())
  398. }
  399. fn set_cursor_visible(&self, visible: bool) -> Result<()> {
  400. Ok(())
  401. }
  402. fn set_cursor_icon(&self, icon: CursorIcon) -> Result<()> {
  403. Ok(())
  404. }
  405. fn set_cursor_position<Pos: Into<Position>>(&self, position: Pos) -> Result<()> {
  406. Ok(())
  407. }
  408. fn set_ignore_cursor_events(&self, ignore: bool) -> Result<()> {
  409. Ok(())
  410. }
  411. fn start_dragging(&self) -> Result<()> {
  412. Ok(())
  413. }
  414. fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
  415. Ok(())
  416. }
  417. fn update_menu_item(&self, id: u16, update: MenuUpdate) -> Result<()> {
  418. Ok(())
  419. }
  420. }
  421. #[cfg(all(desktop, feature = "system-tray"))]
  422. #[derive(Debug, Clone)]
  423. pub struct MockTrayHandler {
  424. context: RuntimeContext,
  425. }
  426. #[cfg(all(desktop, feature = "system-tray"))]
  427. impl TrayHandle for MockTrayHandler {
  428. fn set_icon(&self, icon: Icon) -> Result<()> {
  429. Ok(())
  430. }
  431. fn set_menu(&self, menu: SystemTrayMenu) -> Result<()> {
  432. Ok(())
  433. }
  434. fn update_item(&self, id: u16, update: MenuUpdate) -> Result<()> {
  435. Ok(())
  436. }
  437. #[cfg(target_os = "macos")]
  438. fn set_icon_as_template(&self, is_template: bool) -> Result<()> {
  439. Ok(())
  440. }
  441. #[cfg(target_os = "macos")]
  442. fn set_title(&self, title: &str) -> tauri_runtime::Result<()> {
  443. Ok(())
  444. }
  445. fn destroy(&self) -> Result<()> {
  446. Ok(())
  447. }
  448. }
  449. #[derive(Debug, Clone)]
  450. pub struct EventProxy {}
  451. impl<T: UserEvent> EventLoopProxy<T> for EventProxy {
  452. fn send_event(&self, event: T) -> Result<()> {
  453. Ok(())
  454. }
  455. }
  456. #[derive(Debug)]
  457. pub struct MockRuntime {
  458. pub context: RuntimeContext,
  459. #[cfg(all(desktop, feature = "global-shortcut"))]
  460. global_shortcut_manager: MockGlobalShortcutManager,
  461. #[cfg(feature = "clipboard")]
  462. clipboard_manager: MockClipboardManager,
  463. #[cfg(all(desktop, feature = "system-tray"))]
  464. tray_handler: MockTrayHandler,
  465. }
  466. impl MockRuntime {
  467. fn init() -> Self {
  468. let context = RuntimeContext {
  469. shortcuts: Default::default(),
  470. clipboard: Default::default(),
  471. };
  472. Self {
  473. #[cfg(all(desktop, feature = "global-shortcut"))]
  474. global_shortcut_manager: MockGlobalShortcutManager {
  475. context: context.clone(),
  476. },
  477. #[cfg(feature = "clipboard")]
  478. clipboard_manager: MockClipboardManager {
  479. context: context.clone(),
  480. },
  481. #[cfg(all(desktop, feature = "system-tray"))]
  482. tray_handler: MockTrayHandler {
  483. context: context.clone(),
  484. },
  485. context,
  486. }
  487. }
  488. }
  489. impl<T: UserEvent> Runtime<T> for MockRuntime {
  490. type Dispatcher = MockDispatcher;
  491. type Handle = MockRuntimeHandle;
  492. #[cfg(all(desktop, feature = "global-shortcut"))]
  493. type GlobalShortcutManager = MockGlobalShortcutManager;
  494. #[cfg(feature = "clipboard")]
  495. type ClipboardManager = MockClipboardManager;
  496. #[cfg(all(desktop, feature = "system-tray"))]
  497. type TrayHandler = MockTrayHandler;
  498. type EventLoopProxy = EventProxy;
  499. fn new() -> Result<Self> {
  500. Ok(Self::init())
  501. }
  502. #[cfg(any(windows, target_os = "linux"))]
  503. fn new_any_thread() -> Result<Self> {
  504. Ok(Self::init())
  505. }
  506. fn create_proxy(&self) -> EventProxy {
  507. unimplemented!()
  508. }
  509. fn handle(&self) -> Self::Handle {
  510. MockRuntimeHandle {
  511. context: self.context.clone(),
  512. }
  513. }
  514. #[cfg(all(desktop, feature = "global-shortcut"))]
  515. fn global_shortcut_manager(&self) -> Self::GlobalShortcutManager {
  516. self.global_shortcut_manager.clone()
  517. }
  518. #[cfg(feature = "clipboard")]
  519. fn clipboard_manager(&self) -> Self::ClipboardManager {
  520. self.clipboard_manager.clone()
  521. }
  522. fn create_window(&self, pending: PendingWindow<T, Self>) -> Result<DetachedWindow<T, Self>> {
  523. Ok(DetachedWindow {
  524. label: pending.label,
  525. dispatcher: MockDispatcher {
  526. context: self.context.clone(),
  527. },
  528. menu_ids: Default::default(),
  529. js_event_listeners: Default::default(),
  530. })
  531. }
  532. #[cfg(all(desktop, feature = "system-tray"))]
  533. #[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
  534. fn system_tray(&self, system_tray: SystemTray) -> Result<Self::TrayHandler> {
  535. Ok(self.tray_handler.clone())
  536. }
  537. #[cfg(all(desktop, feature = "system-tray"))]
  538. #[cfg_attr(doc_cfg, doc(cfg(feature = "system-tray")))]
  539. fn on_system_tray_event<F: Fn(TrayId, &SystemTrayEvent) + Send + 'static>(&mut self, f: F) {}
  540. #[cfg(target_os = "macos")]
  541. #[cfg_attr(doc_cfg, doc(cfg(target_os = "macos")))]
  542. fn set_activation_policy(&mut self, activation_policy: tauri_runtime::ActivationPolicy) {}
  543. #[cfg(any(
  544. target_os = "macos",
  545. windows,
  546. target_os = "linux",
  547. target_os = "dragonfly",
  548. target_os = "freebsd",
  549. target_os = "netbsd",
  550. target_os = "openbsd"
  551. ))]
  552. fn run_iteration<F: Fn(RunEvent<T>) + 'static>(
  553. &mut self,
  554. callback: F,
  555. ) -> tauri_runtime::RunIteration {
  556. Default::default()
  557. }
  558. fn run<F: FnMut(RunEvent<T>) + 'static>(self, callback: F) {
  559. loop {
  560. std::thread::sleep(std::time::Duration::from_secs(1));
  561. }
  562. }
  563. }