1use std::{
2 cell::RefCell,
3 collections::HashMap,
4 rc::Rc,
5};
6
7use freya_core::integration::*;
8use freya_engine::prelude::{
9 Canvas,
10 FontCollection,
11};
12pub use keyboard_types::{
13 Code,
14 Key,
15 Modifiers,
16};
17use winit::{
18 event_loop::EventLoopProxy,
19 window::{
20 Window,
21 WindowId,
22 },
23};
24
25use crate::renderer::{
26 NativeEvent,
27 NativeWindowEvent,
28 NativeWindowEventAction,
29};
30
31#[derive(Clone)]
32pub struct PluginHandle {
33 pub proxy: EventLoopProxy<NativeEvent>,
34}
35
36impl PluginHandle {
37 pub fn new(proxy: &EventLoopProxy<NativeEvent>) -> Self {
38 Self {
39 proxy: proxy.clone(),
40 }
41 }
42
43 pub fn send_platform_event(&self, event: PlatformEvent, window_id: WindowId) {
45 self.proxy
46 .send_event(NativeEvent::Window(NativeWindowEvent {
47 window_id,
48 action: NativeWindowEventAction::PlatformEvent(event),
49 }))
50 .ok();
51 }
52
53 pub fn send_event_loop_event(&self, event: NativeEvent) {
55 self.proxy.send_event(event).ok();
56 }
57}
58
59#[derive(Default, Clone)]
61pub struct PluginsManager {
62 plugins: Rc<RefCell<HashMap<&'static str, Box<dyn FreyaPlugin>>>>,
63}
64
65impl PluginsManager {
66 pub fn add_plugin(&mut self, plugin: impl FreyaPlugin + 'static) {
68 self.plugins
69 .borrow_mut()
70 .entry(plugin.plugin_id())
71 .or_insert(Box::new(plugin));
72 }
73
74 pub fn send(&mut self, mut event: PluginEvent, handle: PluginHandle) {
75 for plugin in self.plugins.borrow_mut().values_mut() {
76 plugin.on_event(&mut event, handle.clone())
77 }
78 }
79
80 pub fn tasks_poll_observer<'a>(
82 &'a mut self,
83 window: &'a Window,
84 handle: PluginHandle,
85 ) -> impl FnMut(TasksPollStage) + 'a {
86 move |stage| {
87 let event = match stage {
88 TasksPollStage::Started => PluginEvent::StartedPollingTasks { window },
89 TasksPollStage::Finished => PluginEvent::FinishedPollingTasks { window },
90 };
91 self.send(event, handle.clone())
92 }
93 }
94
95 pub fn wrap_root(&self, mut root: Element) -> Element {
97 for plugin in self.plugins.borrow().values() {
98 root = plugin.root_component(root);
99 }
100 root
101 }
102}
103
104pub enum PluginEvent<'a> {
106 RunnerCreated {
108 runner: &'a mut Runner,
109 },
110 WindowCreated {
112 window: &'a Window,
113 font_collection: &'a FontCollection,
114 tree: &'a Tree,
115 animation_clock: &'a AnimationClock,
116 runner: &'a mut Runner,
117 graphics_driver: &'static str,
118 gpu_name: Option<&'a str>,
119 },
120
121 GraphicsDriverChanged {
123 window: &'a Window,
124 graphics_driver: &'static str,
125 gpu_name: Option<&'a str>,
126 },
127
128 WindowClosed {
130 window: &'a Window,
131 tree: &'a Tree,
132 },
133
134 AfterRedraw {
136 window: &'a Window,
137 font_collection: &'a FontCollection,
138 tree: &'a Tree,
139 },
140
141 BeforePresenting {
143 window: &'a Window,
144 font_collection: &'a FontCollection,
145 tree: &'a Tree,
146 },
147
148 AfterPresenting {
150 window: &'a Window,
151 font_collection: &'a FontCollection,
152 tree: &'a Tree,
153 },
154
155 BeforeRender {
157 window: &'a Window,
158 canvas: &'a Canvas,
159 font_collection: &'a FontCollection,
160 tree: &'a Tree,
161 },
162
163 AfterRender {
165 window: &'a Window,
166 canvas: &'a Canvas,
167 font_collection: &'a FontCollection,
168 tree: &'a Tree,
169 animation_clock: &'a AnimationClock,
170 },
171
172 StartedMeasuringLayout {
174 window: &'a Window,
175 tree: &'a Tree,
176 },
177
178 FinishedMeasuringLayout {
180 window: &'a Window,
181 tree: &'a Tree,
182 },
183
184 StartedMeasuringEvents {
186 window: &'a Window,
187 tree: &'a Tree,
188 },
189
190 FinishedMeasuringEvents {
192 window: &'a Window,
193 tree: &'a Tree,
194 },
195
196 StartedUpdatingTree {
197 window: &'a Window,
198 tree: &'a Tree,
199 },
200
201 FinishedUpdatingTree {
202 window: &'a Window,
203 tree: &'a Tree,
204 },
205
206 StartedPollingTasks {
208 window: &'a Window,
209 },
210
211 FinishedPollingTasks {
213 window: &'a Window,
214 },
215
216 BeforeAccessibility {
217 window: &'a Window,
218 font_collection: &'a FontCollection,
219 tree: &'a Tree,
220 },
221
222 AfterAccessibility {
223 window: &'a Window,
224 font_collection: &'a FontCollection,
225 tree: &'a Tree,
226 },
227
228 KeyboardInput {
230 window: &'a Window,
231 key: Key,
232 code: Code,
233 modifiers: Modifiers,
234 is_pressed: bool,
235 },
236}
237
238pub trait FreyaPlugin {
240 fn plugin_id(&self) -> &'static str;
242
243 fn on_event(&mut self, event: &mut PluginEvent, handle: PluginHandle);
245
246 fn root_component(&self, root: Element) -> Element {
249 root
250 }
251}