spell_framework/
slint_adapter.rs1use crate::configure::LayerConf;
6use slint::platform::{EventLoopProxy, Platform, WindowAdapter};
7use std::{
8 cell::RefCell,
9 rc::Rc,
10 sync::{Arc, Mutex},
11};
12use tracing::{Level, info, span, warn};
13
14thread_local! {
15 pub(crate) static ADAPTERS: RefCell<Vec<Rc<SpellSkiaWinAdapter>>> = const { RefCell::new(Vec::new()) };
16}
17
18#[cfg(not(docsrs))]
19#[cfg(feature = "i-slint-renderer-skia")]
20use crate::skia_non_docs::SpellSkiaWinAdapterReal;
21
22#[cfg(not(docsrs))]
27#[cfg(feature = "i-slint-renderer-skia")]
28pub type SpellSkiaWinAdapter = SpellSkiaWinAdapterReal;
29
30#[cfg(docsrs)]
31use crate::dummy_skia_docs::SpellSkiaWinAdapterDummy;
32
33#[cfg(docsrs)]
38pub type SpellSkiaWinAdapter = SpellSkiaWinAdapterDummy;
39pub struct SpellLayerShell {
42 pub span: span::Span,
43}
44
45impl Default for SpellLayerShell {
46 fn default() -> Self {
48 SpellLayerShell {
49 span: span!(Level::INFO, "slint-log",),
50 }
51 }
52}
53
54impl Platform for SpellLayerShell {
55 fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, slint::PlatformError> {
56 let adapter = ADAPTERS.with(|v| v.borrow().last().unwrap().clone());
57 Ok(adapter)
58 }
59
60 fn debug_log(&self, arguments: core::fmt::Arguments) {
61 self.span.in_scope(|| {
62 if let Some(val) = arguments.as_str() {
63 info!(val);
64 } else {
65 info!("{}", arguments.to_string());
66 }
67 })
68 }
69
70 fn new_event_loop_proxy(&self) -> Option<Box<dyn EventLoopProxy>> {
71 Some(Box::new(SlintEventProxy(ADAPTERS.with(|v| {
72 v.borrow().last().unwrap().slint_event_proxy.clone()
73 }))))
74 }
75}
76
77pub struct SpellMultiWinHandler {
83 pub(crate) windows: Vec<(String, LayerConf)>,
84 pub(crate) adapter: Vec<Rc<SpellSkiaWinAdapter>>,
85 pub(crate) value_given: u32,
86}
87
88impl SpellMultiWinHandler {
89 pub(crate) fn new_lock(lock_outputs: Vec<(String, (u32, u32))>) -> Rc<RefCell<Self>> {
90 let new_locks: Vec<(String, LayerConf)> = lock_outputs
91 .iter()
92 .map(|(output_name, conf)| (output_name.clone(), LayerConf::Lock(conf.0, conf.1)))
93 .collect();
94
95 Rc::new(RefCell::new(SpellMultiWinHandler {
96 windows: new_locks,
97 adapter: Vec::new(),
98 value_given: 0,
99 }))
100 }
101
102 fn request_new_lock(&mut self) -> Rc<dyn WindowAdapter> {
103 self.value_given += 1;
104 let index = self.value_given - 1;
105 self.adapter[index as usize].clone()
106 }
107}
108
109pub struct SpellLockShell {
110 pub window_manager: Rc<RefCell<SpellMultiWinHandler>>,
112 pub span: span::Span,
113}
114
115impl SpellLockShell {
116 pub fn new(window_manager: Rc<RefCell<SpellMultiWinHandler>>) -> Self {
117 SpellLockShell {
118 window_manager,
119 span: span!(Level::INFO, "slint-lock-log",),
120 }
121 }
122}
123
124impl Platform for SpellLockShell {
125 fn create_window_adapter(&self) -> Result<Rc<dyn WindowAdapter>, slint::PlatformError> {
126 let value = self.window_manager.borrow_mut().request_new_lock();
127 Ok(value)
128 }
129
130 fn debug_log(&self, arguments: core::fmt::Arguments) {
131 self.span.in_scope(|| {
132 if let Some(val) = arguments.as_str() {
133 info!(val);
134 } else {
135 info!("{}", arguments.to_string());
136 }
137 })
138 }
139}
140
141#[allow(clippy::type_complexity)]
142struct SlintEventProxy(Arc<Mutex<Vec<Box<dyn FnOnce() + Send>>>>);
143
144impl EventLoopProxy for SlintEventProxy {
145 fn quit_event_loop(&self) -> Result<(), i_slint_core::api::EventLoopError> {
146 Ok(())
147 }
148
149 fn invoke_from_event_loop(
150 &self,
151 event: Box<dyn FnOnce() + Send>,
152 ) -> Result<(), i_slint_core::api::EventLoopError> {
153 if let Ok(mut list_of_event) = self.0.try_lock() {
154 (*list_of_event).push(event);
155 } else {
156 warn!("Slint proxy event could not be processed");
157 }
158 Ok(())
159 }
160}