1pub mod reexports {
2 pub use winit;
3}
4
5use std::sync::Arc;
6
7use crate::{
8 config::LaunchConfig,
9 renderer::{
10 LaunchProxy,
11 NativeEvent,
12 NativeGenericEvent,
13 WinitRenderer,
14 },
15};
16mod accessibility;
17pub mod config;
18mod drivers;
19pub mod extensions;
20pub mod plugins;
21pub mod renderer;
22#[cfg(feature = "tray")]
23mod tray_icon;
24mod window;
25mod winit_mappings;
26
27pub use extensions::*;
28use futures_util::task::{
29 ArcWake,
30 waker,
31};
32
33use crate::winit::event_loop::EventLoopProxy;
34
35pub mod winit {
36 pub use winit::*;
37}
38
39#[cfg(feature = "tray")]
40pub mod tray {
41 pub use tray_icon::*;
42
43 pub use crate::tray_icon::*;
44}
45
46pub fn launch(launch_config: LaunchConfig) {
47 use std::collections::HashMap;
48
49 #[cfg(all(not(debug_assertions), not(target_os = "android")))]
50 {
51 let previous_hook = std::panic::take_hook();
52 std::panic::set_hook(Box::new(move |panic_info| {
53 rfd::MessageDialog::new()
54 .set_title("Fatal Error")
55 .set_description(&panic_info.to_string())
56 .set_level(rfd::MessageLevel::Error)
57 .show();
58 previous_hook(panic_info);
59 std::process::exit(1);
60 }));
61 }
62
63 use freya_core::integration::*;
64 use freya_engine::prelude::{
65 FontCollection,
66 FontMgr,
67 TypefaceFontProvider,
68 };
69 use winit::event_loop::EventLoop;
70
71 let mut event_loop_builder = EventLoop::<NativeEvent>::with_user_event();
72
73 let event_loop = event_loop_builder
74 .build()
75 .expect("Failed to create event loop.");
76
77 let proxy = event_loop.create_proxy();
78
79 let mut font_collection = FontCollection::new();
80 let def_mgr = FontMgr::default();
81 let mut provider = TypefaceFontProvider::new();
82 for (font_name, font_data) in launch_config.embedded_fonts {
83 let ft_type = def_mgr
84 .new_from_data(&font_data, None)
85 .unwrap_or_else(|| panic!("Failed to load font {font_name}."));
86 provider.register_typeface(ft_type, Some(font_name.as_ref()));
87 }
88 let font_mgr: FontMgr = provider.into();
89 font_collection.set_default_font_manager(def_mgr, None);
90 font_collection.set_dynamic_font_manager(font_mgr.clone());
91 font_collection.paragraph_cache_mut().turn_on(false);
92
93 let screen_reader = ScreenReader::new();
94
95 struct FuturesWaker(EventLoopProxy<NativeEvent>);
96
97 impl ArcWake for FuturesWaker {
98 fn wake_by_ref(arc_self: &Arc<Self>) {
99 _ = arc_self
100 .0
101 .send_event(NativeEvent::Generic(NativeGenericEvent::PollFutures));
102 }
103 }
104
105 let waker = waker(Arc::new(FuturesWaker(proxy.clone())));
106
107 let mut renderer = WinitRenderer {
108 windows: HashMap::default(),
109 #[cfg(feature = "tray")]
110 tray: launch_config.tray,
111 #[cfg(all(feature = "tray", not(target_os = "linux")))]
112 tray_icon: None,
113 resumed: false,
114 futures: launch_config
115 .tasks
116 .into_iter()
117 .map(|task| task(LaunchProxy(proxy.clone())))
118 .collect::<Vec<_>>(),
119 proxy,
120 font_manager: font_mgr,
121 font_collection,
122 windows_configs: launch_config.windows_configs,
123 plugins: launch_config.plugins,
124 fallback_fonts: launch_config.fallback_fonts,
125 screen_reader,
126 waker,
127 };
128
129 #[cfg(feature = "tray")]
130 {
131 use crate::{
132 renderer::{
133 NativeTrayEvent,
134 NativeTrayEventAction,
135 },
136 tray::{
137 TrayIconEvent,
138 menu::MenuEvent,
139 },
140 };
141
142 let proxy = renderer.proxy.clone();
143 MenuEvent::set_event_handler(Some(move |event| {
144 let _ = proxy.send_event(NativeEvent::Tray(NativeTrayEvent {
145 action: NativeTrayEventAction::MenuEvent(event),
146 }));
147 }));
148 let proxy = renderer.proxy.clone();
149 TrayIconEvent::set_event_handler(Some(move |event| {
150 let _ = proxy.send_event(NativeEvent::Tray(NativeTrayEvent {
151 action: NativeTrayEventAction::TrayEvent(event),
152 }));
153 }));
154
155 #[cfg(target_os = "linux")]
156 if let Some(tray_icon) = renderer.tray.0.take() {
157 std::thread::spawn(move || {
158 if !gtk::is_initialized() {
159 if gtk::init().is_ok() {
160 tracing::debug!("Tray: GTK initialized");
161 } else {
162 tracing::error!("Tray: Failed to initialize GTK");
163 }
164 }
165
166 let _tray_icon = (tray_icon)();
167
168 gtk::main();
169 });
170 }
171 }
172
173 event_loop.run_app(&mut renderer).unwrap();
174}