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