Skip to main content

ferroui_native/
ferro_native_platform_extensions.rs

1//! The application builder extension that selects the macOS backend, and
2//! the options of the backend.
3
4#[cfg(target_os = "macos")]
5use ferroui_base::{FerroLocator, LocatorExtensions};
6#[cfg(target_os = "macos")]
7use ferroui_controls::AppBuilder;
8
9/// Selects the macOS backend for an application.
10#[cfg(target_os = "macos")]
11pub trait FerroNativePlatformExtensions {
12    /// Uses the standard runtime platform and the macOS windowing
13    /// subsystem.
14    ///
15    /// The backend is initialized with the [`FerroNativePlatformOptions`]
16    /// registered with the builder, or the default options; once the
17    /// application is set up its name becomes the application title.
18    fn use_ferro_native(&self) -> AppBuilder;
19}
20
21#[cfg(target_os = "macos")]
22impl FerroNativePlatformExtensions for AppBuilder {
23    fn use_ferro_native(&self) -> AppBuilder {
24        let builder = self.clone();
25        self.use_standard_runtime_platform_subsystem().use_windowing_subsystem(
26            move || {
27                let options = FerroLocator::current().get_service::<FerroNativePlatformOptions>();
28                let platform =
29                    crate::FerroNativePlatform::initialize(options.as_deref().cloned().unwrap_or_default());
30
31                builder.after_setup(move |_| {
32                    platform.setup_application_name();
33                    platform.setup_application_menu_exporter();
34                    platform.setup_application_dock_menu_exporter();
35                });
36            },
37            "FerroNative",
38        );
39
40        self.clone()
41    }
42}
43
44/// Represents the rendering mode for platform graphics.
45#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
46#[repr(i32)]
47pub enum FerroNativeRenderingMode {
48    /// The toolkit would try to use native OpenGL with GPU rendering.
49    OpenGl = 1,
50    /// The toolkit is rendered into a framebuffer.
51    Software = 2,
52    /// The toolkit would try to use Metal with GPU rendering.
53    Metal = 3,
54}
55
56/// OSX backend options.
57#[derive(Clone, Debug, PartialEq, Eq)]
58pub struct FerroNativePlatformOptions {
59    /// Gets or sets the rendering modes with fallbacks.
60    /// The first element in the list has the highest priority.
61    /// The default value is: [`FerroNativeRenderingMode::Metal`],
62    /// [`FerroNativeRenderingMode::OpenGl`],
63    /// [`FerroNativeRenderingMode::Software`].
64    ///
65    /// If application should work on as wide range of devices as possible,
66    /// at least add [`FerroNativeRenderingMode::Software`] as a fallback
67    /// value.
68    pub rendering_mode: Vec<FerroNativeRenderingMode>,
69
70    /// Embeds popups to the window when set to true. The default value is
71    /// false.
72    pub overlay_popups: bool,
73
74    /// This property should be used in case you want to build the OSX
75    /// native part by yourself and make your app run with it. The default
76    /// value is `None`: the library linked into the application is used.
77    pub ferro_native_library_path: Option<String>,
78
79    /// If you distribute your app in App Store - it should be with sandbox
80    /// enabled. This parameter enables the bookmark APIs of storage items,
81    /// as well as wrapping all storage related calls in secure context. The
82    /// default value is true.
83    pub app_sandbox_enabled: bool,
84}
85
86impl Default for FerroNativePlatformOptions {
87    fn default() -> Self {
88        Self {
89            rendering_mode: vec![
90                FerroNativeRenderingMode::Metal,
91                FerroNativeRenderingMode::OpenGl,
92                FerroNativeRenderingMode::Software,
93            ],
94            overlay_popups: false,
95            ferro_native_library_path: None,
96            app_sandbox_enabled: true,
97        }
98    }
99}
100
101/// OSX front-end options.
102#[derive(Clone, Debug, PartialEq, Eq)]
103pub struct MacOSPlatformOptions {
104    /// Determines whether to show your application in the dock when it
105    /// runs. The default value is true.
106    pub show_in_dock: bool,
107
108    /// By default, items like Quit, Hide are added to the OSX Application
109    /// Menu. You can prevent those items from being added with this
110    /// property. The default value is false.
111    pub disable_default_application_menu_items: bool,
112
113    /// Gets or sets a value indicating whether the native macOS menu bar
114    /// will be enabled for the application.
115    pub disable_native_menus: bool,
116
117    /// Gets or sets a value indicating whether the native macOS should set
118    /// `[NSProcessInfo setProcessName]` in runtime.
119    pub disable_set_process_name: bool,
120
121    /// Gets or sets a value indicating whether the backend can install its
122    /// own AppDelegate. Disabling this can be useful in some scenarios like
123    /// when running as a plugin inside an existing macOS application.
124    pub disable_ferro_app_delegate: bool,
125}
126
127impl Default for MacOSPlatformOptions {
128    fn default() -> Self {
129        Self {
130            show_in_dock: true,
131            disable_default_application_menu_items: false,
132            disable_native_menus: false,
133            disable_set_process_name: false,
134            disable_ferro_app_delegate: false,
135        }
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn defaults_match_the_reference_defaults() {
145        let options = FerroNativePlatformOptions::default();
146        assert_eq!(
147            options.rendering_mode,
148            [FerroNativeRenderingMode::Metal, FerroNativeRenderingMode::OpenGl, FerroNativeRenderingMode::Software]
149        );
150        assert!(!options.overlay_popups);
151        assert_eq!(options.ferro_native_library_path, None);
152        assert!(options.app_sandbox_enabled);
153
154        let mac = MacOSPlatformOptions::default();
155        assert!(mac.show_in_dock);
156        assert!(!mac.disable_default_application_menu_items);
157        assert!(!mac.disable_native_menus);
158        assert!(!mac.disable_set_process_name);
159        assert!(!mac.disable_ferro_app_delegate);
160
161        assert_eq!(FerroNativeRenderingMode::OpenGl as i32, 1);
162        assert_eq!(FerroNativeRenderingMode::Software as i32, 2);
163        assert_eq!(FerroNativeRenderingMode::Metal as i32, 3);
164    }
165}