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