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 use freya_core::integration::*;
50 use freya_engine::prelude::{
51 FontCollection,
52 FontMgr,
53 TypefaceFontProvider,
54 };
55 use winit::event_loop::EventLoop;
56
57 let mut event_loop_builder = EventLoop::<NativeEvent>::with_user_event();
58
59 let event_loop = event_loop_builder
60 .build()
61 .expect("Failed to create event loop.");
62
63 let proxy = event_loop.create_proxy();
64
65 let mut font_collection = FontCollection::new();
66 let def_mgr = FontMgr::default();
67 let mut provider = TypefaceFontProvider::new();
68 for (font_name, font_data) in launch_config.embedded_fonts {
69 let ft_type = def_mgr
70 .new_from_data(&font_data, None)
71 .unwrap_or_else(|| panic!("Failed to load font {font_name}."));
72 provider.register_typeface(ft_type, Some(font_name.as_ref()));
73 }
74 let font_mgr: FontMgr = provider.into();
75 font_collection.set_default_font_manager(def_mgr, None);
76 font_collection.set_dynamic_font_manager(font_mgr.clone());
77 font_collection.paragraph_cache_mut().turn_on(false);
78
79 let screen_reader = ScreenReader::new();
80
81 struct FuturesWaker(EventLoopProxy<NativeEvent>);
82
83 impl ArcWake for FuturesWaker {
84 fn wake_by_ref(arc_self: &Arc<Self>) {
85 _ = arc_self
86 .0
87 .send_event(NativeEvent::Generic(NativeGenericEvent::PollFutures));
88 }
89 }
90
91 let waker = waker(Arc::new(FuturesWaker(proxy.clone())));
92
93 let mut renderer = WinitRenderer {
94 windows: HashMap::default(),
95 #[cfg(feature = "tray")]
96 tray: launch_config.tray,
97 resumed: false,
98 futures: launch_config
99 .tasks
100 .into_iter()
101 .map(|task| task(LaunchProxy(proxy.clone())))
102 .collect::<Vec<_>>(),
103 proxy,
104 font_manager: font_mgr,
105 font_collection,
106 windows_configs: launch_config.windows_configs,
107 plugins: launch_config.plugins,
108 fallback_fonts: launch_config.fallback_fonts,
109 screen_reader,
110 waker,
111 };
112
113 #[cfg(feature = "tray")]
114 {
115 use crate::{
116 renderer::{
117 NativeTrayEvent,
118 NativeTrayEventAction,
119 },
120 tray::{
121 TrayIconEvent,
122 menu::MenuEvent,
123 },
124 };
125
126 let proxy = renderer.proxy.clone();
127 MenuEvent::set_event_handler(Some(move |event| {
128 let _ = proxy.send_event(NativeEvent::Tray(NativeTrayEvent {
129 action: NativeTrayEventAction::MenuEvent(event),
130 }));
131 }));
132 let proxy = renderer.proxy.clone();
133 TrayIconEvent::set_event_handler(Some(move |event| {
134 let _ = proxy.send_event(NativeEvent::Tray(NativeTrayEvent {
135 action: NativeTrayEventAction::TrayEvent(event),
136 }));
137 }));
138
139 #[cfg(target_os = "linux")]
140 if let Some(tray_icon) = renderer.tray.0.take() {
141 std::thread::spawn(move || {
142 gtk::init().expect("Failed to initialize GTK for the Tray Icon.");
143
144 let _tray_icon = (tray_icon)();
145
146 gtk::main();
147 });
148 }
149 }
150
151 event_loop.run_app(&mut renderer).unwrap();
152}