mock_runtime.rs 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  1. // Copyright 2019-2024 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. #![allow(dead_code)]
  5. #![allow(missing_docs)]
  6. use tauri_runtime::{
  7. dpi::{PhysicalPosition, PhysicalSize, Position, Size},
  8. monitor::Monitor,
  9. webview::{DetachedWebview, PendingWebview},
  10. window::{CursorIcon, DetachedWindow, PendingWindow, RawWindow, WindowEvent, WindowId},
  11. window::{WindowBuilder, WindowBuilderBase},
  12. DeviceEventFilter, Error, EventLoopProxy, ExitRequestedEventAction, Icon, ProgressBarState,
  13. Result, RunEvent, Runtime, RuntimeHandle, RuntimeInitArgs, UserAttentionType, UserEvent,
  14. WebviewDispatch, WindowDispatch, WindowEventId,
  15. };
  16. #[cfg(target_os = "macos")]
  17. use tauri_utils::TitleBarStyle;
  18. use tauri_utils::{config::WindowConfig, Theme};
  19. use url::Url;
  20. #[cfg(windows)]
  21. use windows::Win32::Foundation::HWND;
  22. use std::{
  23. cell::RefCell,
  24. collections::HashMap,
  25. fmt,
  26. sync::{
  27. atomic::{AtomicBool, AtomicU32, Ordering},
  28. mpsc::{channel, sync_channel, Receiver, SyncSender},
  29. Arc, Mutex,
  30. },
  31. };
  32. type ShortcutMap = HashMap<String, Box<dyn Fn() + Send + 'static>>;
  33. enum Message {
  34. Task(Box<dyn FnOnce() + Send>),
  35. CloseWindow(WindowId),
  36. DestroyWindow(WindowId),
  37. }
  38. struct Webview;
  39. struct Window {
  40. label: String,
  41. webviews: Vec<Webview>,
  42. }
  43. #[derive(Clone)]
  44. pub struct RuntimeContext {
  45. is_running: Arc<AtomicBool>,
  46. windows: Arc<RefCell<HashMap<WindowId, Window>>>,
  47. shortcuts: Arc<Mutex<ShortcutMap>>,
  48. run_tx: SyncSender<Message>,
  49. next_window_id: Arc<AtomicU32>,
  50. next_webview_id: Arc<AtomicU32>,
  51. next_window_event_id: Arc<AtomicU32>,
  52. next_webview_event_id: Arc<AtomicU32>,
  53. }
  54. // SAFETY: we ensure this type is only used on the main thread.
  55. #[allow(clippy::non_send_fields_in_send_ty)]
  56. unsafe impl Send for RuntimeContext {}
  57. // SAFETY: we ensure this type is only used on the main thread.
  58. #[allow(clippy::non_send_fields_in_send_ty)]
  59. unsafe impl Sync for RuntimeContext {}
  60. impl RuntimeContext {
  61. fn send_message(&self, message: Message) -> Result<()> {
  62. if self.is_running.load(Ordering::Relaxed) {
  63. self
  64. .run_tx
  65. .send(message)
  66. .map_err(|_| Error::FailedToSendMessage)
  67. } else {
  68. match message {
  69. Message::Task(task) => task(),
  70. Message::CloseWindow(id) | Message::DestroyWindow(id) => {
  71. self.windows.borrow_mut().remove(&id);
  72. }
  73. }
  74. Ok(())
  75. }
  76. }
  77. fn next_window_id(&self) -> WindowId {
  78. self.next_window_id.fetch_add(1, Ordering::Relaxed).into()
  79. }
  80. fn next_webview_id(&self) -> u32 {
  81. self.next_webview_id.fetch_add(1, Ordering::Relaxed)
  82. }
  83. fn next_window_event_id(&self) -> WindowEventId {
  84. self.next_window_event_id.fetch_add(1, Ordering::Relaxed)
  85. }
  86. fn next_webview_event_id(&self) -> WindowEventId {
  87. self.next_webview_event_id.fetch_add(1, Ordering::Relaxed)
  88. }
  89. }
  90. impl fmt::Debug for RuntimeContext {
  91. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  92. f.debug_struct("RuntimeContext").finish()
  93. }
  94. }
  95. #[derive(Debug, Clone)]
  96. pub struct MockRuntimeHandle {
  97. context: RuntimeContext,
  98. }
  99. impl<T: UserEvent> RuntimeHandle<T> for MockRuntimeHandle {
  100. type Runtime = MockRuntime;
  101. fn create_proxy(&self) -> EventProxy {
  102. EventProxy {}
  103. }
  104. #[cfg(target_os = "macos")]
  105. #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
  106. fn set_activation_policy(
  107. &self,
  108. activation_policy: tauri_runtime::ActivationPolicy,
  109. ) -> Result<()> {
  110. Ok(())
  111. }
  112. fn request_exit(&self, code: i32) -> Result<()> {
  113. unimplemented!()
  114. }
  115. /// Create a new webview window.
  116. fn create_window<F: Fn(RawWindow<'_>) + Send + 'static>(
  117. &self,
  118. pending: PendingWindow<T, Self::Runtime>,
  119. _after_window_creation: Option<F>,
  120. ) -> Result<DetachedWindow<T, Self::Runtime>> {
  121. let id = self.context.next_window_id();
  122. let (webview_id, webviews) = if let Some(w) = &pending.webview {
  123. (Some(self.context.next_webview_id()), vec![Webview])
  124. } else {
  125. (None, Vec::new())
  126. };
  127. self.context.windows.borrow_mut().insert(
  128. id,
  129. Window {
  130. label: pending.label.clone(),
  131. webviews,
  132. },
  133. );
  134. let webview = webview_id.map(|id| DetachedWebview {
  135. label: pending.label.clone(),
  136. dispatcher: MockWebviewDispatcher {
  137. id,
  138. context: self.context.clone(),
  139. url: Arc::new(Mutex::new(pending.webview.unwrap().url)),
  140. last_evaluated_script: Default::default(),
  141. },
  142. });
  143. Ok(DetachedWindow {
  144. id,
  145. label: pending.label,
  146. dispatcher: MockWindowDispatcher {
  147. id,
  148. context: self.context.clone(),
  149. },
  150. webview,
  151. })
  152. }
  153. fn create_webview(
  154. &self,
  155. window_id: WindowId,
  156. pending: PendingWebview<T, Self::Runtime>,
  157. ) -> Result<DetachedWebview<T, Self::Runtime>> {
  158. let id = self.context.next_webview_id();
  159. let webview = Webview;
  160. if let Some(w) = self.context.windows.borrow_mut().get_mut(&window_id) {
  161. w.webviews.push(webview);
  162. }
  163. Ok(DetachedWebview {
  164. label: pending.label,
  165. dispatcher: MockWebviewDispatcher {
  166. id,
  167. context: self.context.clone(),
  168. last_evaluated_script: Default::default(),
  169. url: Arc::new(Mutex::new(pending.url)),
  170. },
  171. })
  172. }
  173. /// Run a task on the main thread.
  174. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  175. self.context.send_message(Message::Task(Box::new(f)))
  176. }
  177. fn display_handle(
  178. &self,
  179. ) -> std::result::Result<raw_window_handle::DisplayHandle<'_>, raw_window_handle::HandleError> {
  180. #[cfg(target_os = "linux")]
  181. return Ok(unsafe {
  182. raw_window_handle::DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::Xlib(
  183. raw_window_handle::XlibDisplayHandle::new(None, 0),
  184. ))
  185. });
  186. #[cfg(target_os = "macos")]
  187. return Ok(unsafe {
  188. raw_window_handle::DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::AppKit(
  189. raw_window_handle::AppKitDisplayHandle::new(),
  190. ))
  191. });
  192. #[cfg(windows)]
  193. return Ok(unsafe {
  194. raw_window_handle::DisplayHandle::borrow_raw(raw_window_handle::RawDisplayHandle::Windows(
  195. raw_window_handle::WindowsDisplayHandle::new(),
  196. ))
  197. });
  198. #[cfg(not(any(target_os = "linux", target_os = "macos", windows)))]
  199. unimplemented!();
  200. }
  201. fn primary_monitor(&self) -> Option<Monitor> {
  202. unimplemented!()
  203. }
  204. fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor> {
  205. unimplemented!()
  206. }
  207. fn available_monitors(&self) -> Vec<Monitor> {
  208. unimplemented!()
  209. }
  210. fn set_theme(&self, theme: Option<Theme>) {
  211. unimplemented!()
  212. }
  213. /// Shows the application, but does not automatically focus it.
  214. #[cfg(target_os = "macos")]
  215. fn show(&self) -> Result<()> {
  216. Ok(())
  217. }
  218. /// Hides the application.
  219. #[cfg(target_os = "macos")]
  220. fn hide(&self) -> Result<()> {
  221. Ok(())
  222. }
  223. #[cfg(target_os = "android")]
  224. fn find_class<'a>(
  225. &self,
  226. env: &mut jni::JNIEnv<'a>,
  227. activity: &jni::objects::JObject<'_>,
  228. name: impl Into<String>,
  229. ) -> std::result::Result<jni::objects::JClass<'a>, jni::errors::Error> {
  230. todo!()
  231. }
  232. #[cfg(target_os = "android")]
  233. fn run_on_android_context<F>(&self, f: F)
  234. where
  235. F: FnOnce(&mut jni::JNIEnv, &jni::objects::JObject, &jni::objects::JObject) + Send + 'static,
  236. {
  237. todo!()
  238. }
  239. fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
  240. Ok(PhysicalPosition::new(0.0, 0.0))
  241. }
  242. }
  243. #[derive(Debug, Clone)]
  244. pub struct MockWebviewDispatcher {
  245. id: u32,
  246. context: RuntimeContext,
  247. url: Arc<Mutex<String>>,
  248. last_evaluated_script: Arc<Mutex<Option<String>>>,
  249. }
  250. impl MockWebviewDispatcher {
  251. pub fn last_evaluated_script(&self) -> Option<String> {
  252. self.last_evaluated_script.lock().unwrap().clone()
  253. }
  254. }
  255. #[derive(Debug, Clone)]
  256. pub struct MockWindowDispatcher {
  257. id: WindowId,
  258. context: RuntimeContext,
  259. }
  260. #[derive(Debug, Clone)]
  261. pub struct MockWindowBuilder {}
  262. impl WindowBuilderBase for MockWindowBuilder {}
  263. impl WindowBuilder for MockWindowBuilder {
  264. fn new() -> Self {
  265. Self {}
  266. }
  267. fn with_config(config: &WindowConfig) -> Self {
  268. Self {}
  269. }
  270. fn center(self) -> Self {
  271. self
  272. }
  273. fn position(self, x: f64, y: f64) -> Self {
  274. self
  275. }
  276. fn inner_size(self, min_width: f64, min_height: f64) -> Self {
  277. self
  278. }
  279. fn min_inner_size(self, min_width: f64, min_height: f64) -> Self {
  280. self
  281. }
  282. fn max_inner_size(self, max_width: f64, max_height: f64) -> Self {
  283. self
  284. }
  285. fn inner_size_constraints(
  286. self,
  287. constraints: tauri_runtime::window::WindowSizeConstraints,
  288. ) -> Self {
  289. self
  290. }
  291. fn resizable(self, resizable: bool) -> Self {
  292. self
  293. }
  294. fn maximizable(self, resizable: bool) -> Self {
  295. self
  296. }
  297. fn minimizable(self, resizable: bool) -> Self {
  298. self
  299. }
  300. fn closable(self, resizable: bool) -> Self {
  301. self
  302. }
  303. fn title<S: Into<String>>(self, title: S) -> Self {
  304. self
  305. }
  306. fn fullscreen(self, fullscreen: bool) -> Self {
  307. self
  308. }
  309. fn focused(self, focused: bool) -> Self {
  310. self
  311. }
  312. fn maximized(self, maximized: bool) -> Self {
  313. self
  314. }
  315. fn visible(self, visible: bool) -> Self {
  316. self
  317. }
  318. #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))]
  319. #[cfg_attr(
  320. docsrs,
  321. doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api")))
  322. )]
  323. fn transparent(self, transparent: bool) -> Self {
  324. self
  325. }
  326. fn decorations(self, decorations: bool) -> Self {
  327. self
  328. }
  329. fn always_on_bottom(self, always_on_bottom: bool) -> Self {
  330. self
  331. }
  332. fn always_on_top(self, always_on_top: bool) -> Self {
  333. self
  334. }
  335. fn visible_on_all_workspaces(self, visible_on_all_workspaces: bool) -> Self {
  336. self
  337. }
  338. fn content_protected(self, protected: bool) -> Self {
  339. self
  340. }
  341. fn icon(self, icon: Icon<'_>) -> Result<Self> {
  342. Ok(self)
  343. }
  344. fn skip_taskbar(self, skip: bool) -> Self {
  345. self
  346. }
  347. fn shadow(self, enable: bool) -> Self {
  348. self
  349. }
  350. #[cfg(windows)]
  351. fn owner(self, owner: HWND) -> Self {
  352. self
  353. }
  354. #[cfg(windows)]
  355. fn parent(self, parent: HWND) -> Self {
  356. self
  357. }
  358. #[cfg(target_os = "macos")]
  359. fn parent(self, parent: *mut std::ffi::c_void) -> Self {
  360. self
  361. }
  362. #[cfg(any(
  363. target_os = "linux",
  364. target_os = "dragonfly",
  365. target_os = "freebsd",
  366. target_os = "netbsd",
  367. target_os = "openbsd"
  368. ))]
  369. fn transient_for(self, parent: &impl gtk::glib::IsA<gtk::Window>) -> Self {
  370. self
  371. }
  372. #[cfg(windows)]
  373. fn drag_and_drop(self, enabled: bool) -> Self {
  374. self
  375. }
  376. #[cfg(target_os = "macos")]
  377. fn title_bar_style(self, style: TitleBarStyle) -> Self {
  378. self
  379. }
  380. #[cfg(target_os = "macos")]
  381. fn hidden_title(self, transparent: bool) -> Self {
  382. self
  383. }
  384. #[cfg(target_os = "macos")]
  385. fn tabbing_identifier(self, identifier: &str) -> Self {
  386. self
  387. }
  388. fn theme(self, theme: Option<Theme>) -> Self {
  389. self
  390. }
  391. fn has_icon(&self) -> bool {
  392. false
  393. }
  394. fn get_theme(&self) -> Option<Theme> {
  395. None
  396. }
  397. }
  398. impl<T: UserEvent> WebviewDispatch<T> for MockWebviewDispatcher {
  399. type Runtime = MockRuntime;
  400. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  401. self.context.send_message(Message::Task(Box::new(f)))
  402. }
  403. fn on_webview_event<F: Fn(&tauri_runtime::window::WebviewEvent) + Send + 'static>(
  404. &self,
  405. f: F,
  406. ) -> tauri_runtime::WebviewEventId {
  407. self.context.next_window_event_id()
  408. }
  409. fn with_webview<F: FnOnce(Box<dyn std::any::Any>) + Send + 'static>(&self, f: F) -> Result<()> {
  410. Ok(())
  411. }
  412. #[cfg(any(debug_assertions, feature = "devtools"))]
  413. fn open_devtools(&self) {}
  414. #[cfg(any(debug_assertions, feature = "devtools"))]
  415. fn close_devtools(&self) {}
  416. #[cfg(any(debug_assertions, feature = "devtools"))]
  417. fn is_devtools_open(&self) -> Result<bool> {
  418. Ok(false)
  419. }
  420. fn set_zoom(&self, scale_factor: f64) -> Result<()> {
  421. Ok(())
  422. }
  423. fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
  424. self
  425. .last_evaluated_script
  426. .lock()
  427. .unwrap()
  428. .replace(script.into());
  429. Ok(())
  430. }
  431. fn url(&self) -> Result<String> {
  432. Ok(self.url.lock().unwrap().clone())
  433. }
  434. fn bounds(&self) -> Result<tauri_runtime::Rect> {
  435. Ok(tauri_runtime::Rect::default())
  436. }
  437. fn position(&self) -> Result<PhysicalPosition<i32>> {
  438. Ok(PhysicalPosition { x: 0, y: 0 })
  439. }
  440. fn size(&self) -> Result<PhysicalSize<u32>> {
  441. Ok(PhysicalSize {
  442. width: 0,
  443. height: 0,
  444. })
  445. }
  446. fn navigate(&self, url: Url) -> Result<()> {
  447. *self.url.lock().unwrap() = url.to_string();
  448. Ok(())
  449. }
  450. fn print(&self) -> Result<()> {
  451. Ok(())
  452. }
  453. fn close(&self) -> Result<()> {
  454. Ok(())
  455. }
  456. fn set_bounds(&self, bounds: tauri_runtime::Rect) -> Result<()> {
  457. Ok(())
  458. }
  459. fn set_size(&self, _size: Size) -> Result<()> {
  460. Ok(())
  461. }
  462. fn set_position(&self, _position: Position) -> Result<()> {
  463. Ok(())
  464. }
  465. fn set_focus(&self) -> Result<()> {
  466. Ok(())
  467. }
  468. fn reparent(&self, window_id: WindowId) -> Result<()> {
  469. Ok(())
  470. }
  471. fn set_auto_resize(&self, auto_resize: bool) -> Result<()> {
  472. Ok(())
  473. }
  474. fn clear_all_browsing_data(&self) -> Result<()> {
  475. Ok(())
  476. }
  477. fn hide(&self) -> Result<()> {
  478. Ok(())
  479. }
  480. fn show(&self) -> Result<()> {
  481. Ok(())
  482. }
  483. }
  484. impl<T: UserEvent> WindowDispatch<T> for MockWindowDispatcher {
  485. type Runtime = MockRuntime;
  486. type WindowBuilder = MockWindowBuilder;
  487. fn run_on_main_thread<F: FnOnce() + Send + 'static>(&self, f: F) -> Result<()> {
  488. self.context.send_message(Message::Task(Box::new(f)))
  489. }
  490. fn on_window_event<F: Fn(&WindowEvent) + Send + 'static>(&self, f: F) -> WindowEventId {
  491. self.context.next_window_event_id()
  492. }
  493. fn scale_factor(&self) -> Result<f64> {
  494. Ok(1.0)
  495. }
  496. fn inner_position(&self) -> Result<PhysicalPosition<i32>> {
  497. Ok(PhysicalPosition { x: 0, y: 0 })
  498. }
  499. fn outer_position(&self) -> Result<PhysicalPosition<i32>> {
  500. Ok(PhysicalPosition { x: 0, y: 0 })
  501. }
  502. fn inner_size(&self) -> Result<PhysicalSize<u32>> {
  503. Ok(PhysicalSize {
  504. width: 0,
  505. height: 0,
  506. })
  507. }
  508. fn outer_size(&self) -> Result<PhysicalSize<u32>> {
  509. Ok(PhysicalSize {
  510. width: 0,
  511. height: 0,
  512. })
  513. }
  514. fn is_fullscreen(&self) -> Result<bool> {
  515. Ok(false)
  516. }
  517. fn is_minimized(&self) -> Result<bool> {
  518. Ok(false)
  519. }
  520. fn is_maximized(&self) -> Result<bool> {
  521. Ok(false)
  522. }
  523. fn is_focused(&self) -> Result<bool> {
  524. Ok(false)
  525. }
  526. fn is_decorated(&self) -> Result<bool> {
  527. Ok(false)
  528. }
  529. fn is_resizable(&self) -> Result<bool> {
  530. Ok(false)
  531. }
  532. fn is_maximizable(&self) -> Result<bool> {
  533. Ok(true)
  534. }
  535. fn is_minimizable(&self) -> Result<bool> {
  536. Ok(true)
  537. }
  538. fn is_closable(&self) -> Result<bool> {
  539. Ok(true)
  540. }
  541. fn is_visible(&self) -> Result<bool> {
  542. Ok(true)
  543. }
  544. fn title(&self) -> Result<String> {
  545. Ok(String::new())
  546. }
  547. fn current_monitor(&self) -> Result<Option<Monitor>> {
  548. Ok(None)
  549. }
  550. fn primary_monitor(&self) -> Result<Option<Monitor>> {
  551. Ok(None)
  552. }
  553. fn monitor_from_point(&self, x: f64, y: f64) -> Result<Option<Monitor>> {
  554. Ok(None)
  555. }
  556. fn available_monitors(&self) -> Result<Vec<Monitor>> {
  557. Ok(Vec::new())
  558. }
  559. fn theme(&self) -> Result<Theme> {
  560. Ok(Theme::Light)
  561. }
  562. #[cfg(any(
  563. target_os = "linux",
  564. target_os = "dragonfly",
  565. target_os = "freebsd",
  566. target_os = "netbsd",
  567. target_os = "openbsd"
  568. ))]
  569. fn gtk_window(&self) -> Result<gtk::ApplicationWindow> {
  570. unimplemented!()
  571. }
  572. #[cfg(any(
  573. target_os = "linux",
  574. target_os = "dragonfly",
  575. target_os = "freebsd",
  576. target_os = "netbsd",
  577. target_os = "openbsd"
  578. ))]
  579. fn default_vbox(&self) -> Result<gtk::Box> {
  580. unimplemented!()
  581. }
  582. fn window_handle(
  583. &self,
  584. ) -> std::result::Result<raw_window_handle::WindowHandle<'_>, raw_window_handle::HandleError> {
  585. #[cfg(target_os = "linux")]
  586. return unsafe {
  587. Ok(raw_window_handle::WindowHandle::borrow_raw(
  588. raw_window_handle::RawWindowHandle::Xlib(raw_window_handle::XlibWindowHandle::new(0)),
  589. ))
  590. };
  591. #[cfg(target_os = "macos")]
  592. return unsafe {
  593. Ok(raw_window_handle::WindowHandle::borrow_raw(
  594. raw_window_handle::RawWindowHandle::AppKit(raw_window_handle::AppKitWindowHandle::new(
  595. std::ptr::NonNull::from(&()).cast(),
  596. )),
  597. ))
  598. };
  599. #[cfg(windows)]
  600. return unsafe {
  601. Ok(raw_window_handle::WindowHandle::borrow_raw(
  602. raw_window_handle::RawWindowHandle::Win32(raw_window_handle::Win32WindowHandle::new(
  603. std::num::NonZeroIsize::MIN,
  604. )),
  605. ))
  606. };
  607. #[cfg(not(any(target_os = "linux", target_os = "macos", windows)))]
  608. unimplemented!();
  609. }
  610. fn center(&self) -> Result<()> {
  611. Ok(())
  612. }
  613. fn request_user_attention(&self, request_type: Option<UserAttentionType>) -> Result<()> {
  614. Ok(())
  615. }
  616. fn create_window<F: Fn(RawWindow<'_>) + Send + 'static>(
  617. &mut self,
  618. pending: PendingWindow<T, Self::Runtime>,
  619. _after_window_creation: Option<F>,
  620. ) -> Result<DetachedWindow<T, Self::Runtime>> {
  621. let id = self.context.next_window_id();
  622. let (webview_id, webviews) = if let Some(w) = &pending.webview {
  623. (Some(self.context.next_webview_id()), vec![Webview])
  624. } else {
  625. (None, Vec::new())
  626. };
  627. self.context.windows.borrow_mut().insert(
  628. id,
  629. Window {
  630. label: pending.label.clone(),
  631. webviews,
  632. },
  633. );
  634. let webview = webview_id.map(|id| DetachedWebview {
  635. label: pending.label.clone(),
  636. dispatcher: MockWebviewDispatcher {
  637. id,
  638. context: self.context.clone(),
  639. url: Arc::new(Mutex::new(pending.webview.unwrap().url)),
  640. last_evaluated_script: Default::default(),
  641. },
  642. });
  643. Ok(DetachedWindow {
  644. id,
  645. label: pending.label,
  646. dispatcher: MockWindowDispatcher {
  647. id,
  648. context: self.context.clone(),
  649. },
  650. webview,
  651. })
  652. }
  653. fn create_webview(
  654. &mut self,
  655. pending: PendingWebview<T, Self::Runtime>,
  656. ) -> Result<DetachedWebview<T, Self::Runtime>> {
  657. let id = self.context.next_webview_id();
  658. let webview = Webview;
  659. if let Some(w) = self.context.windows.borrow_mut().get_mut(&self.id) {
  660. w.webviews.push(webview);
  661. }
  662. Ok(DetachedWebview {
  663. label: pending.label,
  664. dispatcher: MockWebviewDispatcher {
  665. id,
  666. context: self.context.clone(),
  667. last_evaluated_script: Default::default(),
  668. url: Arc::new(Mutex::new(pending.url)),
  669. },
  670. })
  671. }
  672. fn set_resizable(&self, resizable: bool) -> Result<()> {
  673. Ok(())
  674. }
  675. fn set_maximizable(&self, maximizable: bool) -> Result<()> {
  676. Ok(())
  677. }
  678. fn set_minimizable(&self, minimizable: bool) -> Result<()> {
  679. Ok(())
  680. }
  681. fn set_closable(&self, closable: bool) -> Result<()> {
  682. Ok(())
  683. }
  684. fn set_title<S: Into<String>>(&self, title: S) -> Result<()> {
  685. Ok(())
  686. }
  687. fn maximize(&self) -> Result<()> {
  688. Ok(())
  689. }
  690. fn unmaximize(&self) -> Result<()> {
  691. Ok(())
  692. }
  693. fn minimize(&self) -> Result<()> {
  694. Ok(())
  695. }
  696. fn unminimize(&self) -> Result<()> {
  697. Ok(())
  698. }
  699. fn show(&self) -> Result<()> {
  700. Ok(())
  701. }
  702. fn hide(&self) -> Result<()> {
  703. Ok(())
  704. }
  705. fn close(&self) -> Result<()> {
  706. self.context.send_message(Message::CloseWindow(self.id))?;
  707. Ok(())
  708. }
  709. fn destroy(&self) -> Result<()> {
  710. self.context.send_message(Message::DestroyWindow(self.id))?;
  711. Ok(())
  712. }
  713. fn set_decorations(&self, decorations: bool) -> Result<()> {
  714. Ok(())
  715. }
  716. fn set_shadow(&self, shadow: bool) -> Result<()> {
  717. Ok(())
  718. }
  719. fn set_always_on_bottom(&self, always_on_bottom: bool) -> Result<()> {
  720. Ok(())
  721. }
  722. fn set_always_on_top(&self, always_on_top: bool) -> Result<()> {
  723. Ok(())
  724. }
  725. fn set_visible_on_all_workspaces(&self, visible_on_all_workspaces: bool) -> Result<()> {
  726. Ok(())
  727. }
  728. fn set_content_protected(&self, protected: bool) -> Result<()> {
  729. Ok(())
  730. }
  731. fn set_size(&self, size: Size) -> Result<()> {
  732. Ok(())
  733. }
  734. fn set_min_size(&self, size: Option<Size>) -> Result<()> {
  735. Ok(())
  736. }
  737. fn set_max_size(&self, size: Option<Size>) -> Result<()> {
  738. Ok(())
  739. }
  740. fn set_position(&self, position: Position) -> Result<()> {
  741. Ok(())
  742. }
  743. fn set_fullscreen(&self, fullscreen: bool) -> Result<()> {
  744. Ok(())
  745. }
  746. fn set_focus(&self) -> Result<()> {
  747. Ok(())
  748. }
  749. fn set_icon(&self, icon: Icon<'_>) -> Result<()> {
  750. Ok(())
  751. }
  752. fn set_skip_taskbar(&self, skip: bool) -> Result<()> {
  753. Ok(())
  754. }
  755. fn set_cursor_grab(&self, grab: bool) -> Result<()> {
  756. Ok(())
  757. }
  758. fn set_cursor_visible(&self, visible: bool) -> Result<()> {
  759. Ok(())
  760. }
  761. fn set_cursor_icon(&self, icon: CursorIcon) -> Result<()> {
  762. Ok(())
  763. }
  764. fn set_cursor_position<Pos: Into<Position>>(&self, position: Pos) -> Result<()> {
  765. Ok(())
  766. }
  767. fn set_ignore_cursor_events(&self, ignore: bool) -> Result<()> {
  768. Ok(())
  769. }
  770. fn start_dragging(&self) -> Result<()> {
  771. Ok(())
  772. }
  773. fn start_resize_dragging(&self, direction: tauri_runtime::ResizeDirection) -> Result<()> {
  774. Ok(())
  775. }
  776. fn set_progress_bar(&self, progress_state: ProgressBarState) -> Result<()> {
  777. Ok(())
  778. }
  779. fn set_title_bar_style(&self, style: tauri_utils::TitleBarStyle) -> Result<()> {
  780. Ok(())
  781. }
  782. fn set_size_constraints(
  783. &self,
  784. constraints: tauri_runtime::window::WindowSizeConstraints,
  785. ) -> Result<()> {
  786. Ok(())
  787. }
  788. fn set_theme(&self, theme: Option<Theme>) -> Result<()> {
  789. Ok(())
  790. }
  791. }
  792. #[derive(Debug, Clone)]
  793. pub struct EventProxy {}
  794. impl<T: UserEvent> EventLoopProxy<T> for EventProxy {
  795. fn send_event(&self, event: T) -> Result<()> {
  796. Ok(())
  797. }
  798. }
  799. #[derive(Debug)]
  800. pub struct MockRuntime {
  801. is_running: Arc<AtomicBool>,
  802. pub context: RuntimeContext,
  803. run_rx: Receiver<Message>,
  804. }
  805. impl MockRuntime {
  806. fn init() -> Self {
  807. let is_running = Arc::new(AtomicBool::new(false));
  808. let (tx, rx) = sync_channel(256);
  809. let context = RuntimeContext {
  810. is_running: is_running.clone(),
  811. windows: Default::default(),
  812. shortcuts: Default::default(),
  813. run_tx: tx,
  814. next_window_id: Default::default(),
  815. next_webview_id: Default::default(),
  816. next_window_event_id: Default::default(),
  817. next_webview_event_id: Default::default(),
  818. };
  819. Self {
  820. is_running,
  821. context,
  822. run_rx: rx,
  823. }
  824. }
  825. }
  826. impl<T: UserEvent> Runtime<T> for MockRuntime {
  827. type WindowDispatcher = MockWindowDispatcher;
  828. type WebviewDispatcher = MockWebviewDispatcher;
  829. type Handle = MockRuntimeHandle;
  830. type EventLoopProxy = EventProxy;
  831. fn new(_args: RuntimeInitArgs) -> Result<Self> {
  832. Ok(Self::init())
  833. }
  834. #[cfg(any(windows, target_os = "linux"))]
  835. fn new_any_thread(_args: RuntimeInitArgs) -> Result<Self> {
  836. Ok(Self::init())
  837. }
  838. fn create_proxy(&self) -> EventProxy {
  839. EventProxy {}
  840. }
  841. fn handle(&self) -> Self::Handle {
  842. MockRuntimeHandle {
  843. context: self.context.clone(),
  844. }
  845. }
  846. fn create_window<F: Fn(RawWindow<'_>) + Send + 'static>(
  847. &self,
  848. pending: PendingWindow<T, Self>,
  849. _after_window_creation: Option<F>,
  850. ) -> Result<DetachedWindow<T, Self>> {
  851. let id = self.context.next_window_id();
  852. let (webview_id, webviews) = if let Some(w) = &pending.webview {
  853. (Some(self.context.next_webview_id()), vec![Webview])
  854. } else {
  855. (None, Vec::new())
  856. };
  857. self.context.windows.borrow_mut().insert(
  858. id,
  859. Window {
  860. label: pending.label.clone(),
  861. webviews,
  862. },
  863. );
  864. let webview = webview_id.map(|id| DetachedWebview {
  865. label: pending.label.clone(),
  866. dispatcher: MockWebviewDispatcher {
  867. id,
  868. context: self.context.clone(),
  869. url: Arc::new(Mutex::new(pending.webview.unwrap().url)),
  870. last_evaluated_script: Default::default(),
  871. },
  872. });
  873. Ok(DetachedWindow {
  874. id,
  875. label: pending.label,
  876. dispatcher: MockWindowDispatcher {
  877. id,
  878. context: self.context.clone(),
  879. },
  880. webview,
  881. })
  882. }
  883. fn create_webview(
  884. &self,
  885. window_id: WindowId,
  886. pending: PendingWebview<T, Self>,
  887. ) -> Result<DetachedWebview<T, Self>> {
  888. let id = self.context.next_webview_id();
  889. let webview = Webview;
  890. if let Some(w) = self.context.windows.borrow_mut().get_mut(&window_id) {
  891. w.webviews.push(webview);
  892. }
  893. Ok(DetachedWebview {
  894. label: pending.label,
  895. dispatcher: MockWebviewDispatcher {
  896. id,
  897. context: self.context.clone(),
  898. last_evaluated_script: Default::default(),
  899. url: Arc::new(Mutex::new(pending.url)),
  900. },
  901. })
  902. }
  903. fn primary_monitor(&self) -> Option<Monitor> {
  904. unimplemented!()
  905. }
  906. fn monitor_from_point(&self, x: f64, y: f64) -> Option<Monitor> {
  907. unimplemented!()
  908. }
  909. fn available_monitors(&self) -> Vec<Monitor> {
  910. unimplemented!()
  911. }
  912. fn set_theme(&self, theme: Option<Theme>) {
  913. unimplemented!()
  914. }
  915. #[cfg(target_os = "macos")]
  916. #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
  917. fn set_activation_policy(&mut self, activation_policy: tauri_runtime::ActivationPolicy) {}
  918. #[cfg(target_os = "macos")]
  919. #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
  920. fn show(&self) {}
  921. #[cfg(target_os = "macos")]
  922. #[cfg_attr(docsrs, doc(cfg(target_os = "macos")))]
  923. fn hide(&self) {}
  924. fn set_device_event_filter(&mut self, filter: DeviceEventFilter) {}
  925. #[cfg(any(
  926. target_os = "macos",
  927. windows,
  928. target_os = "linux",
  929. target_os = "dragonfly",
  930. target_os = "freebsd",
  931. target_os = "netbsd",
  932. target_os = "openbsd"
  933. ))]
  934. fn run_iteration<F: FnMut(RunEvent<T>)>(&mut self, callback: F) {}
  935. fn run<F: FnMut(RunEvent<T>) + 'static>(self, mut callback: F) {
  936. self.is_running.store(true, Ordering::Relaxed);
  937. callback(RunEvent::Ready);
  938. loop {
  939. if let Ok(m) = self.run_rx.try_recv() {
  940. match m {
  941. Message::Task(p) => p(),
  942. Message::CloseWindow(id) => {
  943. let label = self
  944. .context
  945. .windows
  946. .borrow()
  947. .get(&id)
  948. .map(|w| w.label.clone());
  949. if let Some(label) = label {
  950. let (tx, rx) = channel();
  951. callback(RunEvent::WindowEvent {
  952. label,
  953. event: WindowEvent::CloseRequested { signal_tx: tx },
  954. });
  955. let should_prevent = matches!(rx.try_recv(), Ok(true));
  956. if !should_prevent {
  957. self.context.windows.borrow_mut().remove(&id);
  958. let is_empty = self.context.windows.borrow().is_empty();
  959. if is_empty {
  960. let (tx, rx) = channel();
  961. callback(RunEvent::ExitRequested { code: None, tx });
  962. let recv = rx.try_recv();
  963. let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent));
  964. if !should_prevent {
  965. break;
  966. }
  967. }
  968. }
  969. }
  970. }
  971. Message::DestroyWindow(id) => {
  972. let removed = self.context.windows.borrow_mut().remove(&id).is_some();
  973. if removed {
  974. let is_empty = self.context.windows.borrow().is_empty();
  975. if is_empty {
  976. let (tx, rx) = channel();
  977. callback(RunEvent::ExitRequested { code: None, tx });
  978. let recv = rx.try_recv();
  979. let should_prevent = matches!(recv, Ok(ExitRequestedEventAction::Prevent));
  980. if !should_prevent {
  981. break;
  982. }
  983. }
  984. }
  985. }
  986. }
  987. }
  988. callback(RunEvent::MainEventsCleared);
  989. std::thread::sleep(std::time::Duration::from_secs(1));
  990. }
  991. callback(RunEvent::Exit);
  992. }
  993. fn cursor_position(&self) -> Result<PhysicalPosition<f64>> {
  994. Ok(PhysicalPosition::new(0.0, 0.0))
  995. }
  996. }