1#![doc(
2 html_logo_url = "https://raw.githubusercontent.com/VimYoung/Spell/main/spell-framework/assets/spell_trans.png"
3)]
4#![doc(
5 html_favicon_url = "https://raw.githubusercontent.com/VimYoung/Spell/main/spell-framework/assets/spell_trans.ico"
6)]
7#![doc = include_str!("../docs/entry.md")]
9#[warn(missing_docs)]
10mod configure;
11mod dbus_window_state;
12#[cfg(docsrs)]
13mod dummy_skia_docs;
14pub mod forge;
15#[cfg(feature = "i-slint-renderer-skia")]
16#[cfg(not(docsrs))]
18#[doc(hidden)]
19mod skia_non_docs;
20pub mod slint_adapter;
21pub mod vault;
22pub mod wayland_adapter;
23pub mod layer_properties {
28 pub use crate::{
29 configure::WindowConf,
30 dbus_window_state::{DataType, ForeignController},
31 };
32 pub use smithay_client_toolkit::reexports::calloop::timer::{TimeoutAction, Timer};
33 pub use smithay_client_toolkit::shell::wlr_layer::Anchor as LayerAnchor;
34 pub use smithay_client_toolkit::shell::wlr_layer::KeyboardInteractivity as BoardType;
35 pub use smithay_client_toolkit::shell::wlr_layer::Layer as LayerType;
36}
37
38use dbus_window_state::{ForeignController, InternalHandle, deploy_zbus_service};
39use smithay_client_toolkit::reexports::client::{DispatchError, backend};
40use std::{
41 error::Error,
42 sync::{Arc, RwLock},
43};
44use tokio::sync::mpsc;
45use wayland_adapter::SpellWin;
46
47use zbus::Error as BusError;
48
49#[derive(Debug)]
52pub enum Handle {
53 HideWindow,
55 ShowWinAgain,
57 ToggleWindow,
59 GrabKeyboardFocus,
61 RemoveKeyboardFocus,
63 AddInputRegion(i32, i32, i32, i32),
65 SubtractInputRegion(i32, i32, i32, i32),
67 AddOpaqueRegion(i32, i32, i32, i32),
69 SubtractOpaqueRegion(i32, i32, i32, i32),
71}
72
73type State = Arc<RwLock<Box<dyn ForeignController>>>;
74
75pub fn enchant_spells<F>(
76 mut waywindows: Vec<SpellWin>,
77 states: Vec<Option<State>>,
79 mut set_callbacks: Vec<Option<F>>,
80) -> Result<(), Box<dyn Error>>
81where
82 F: FnMut(Arc<RwLock<Box<dyn ForeignController>>>),
83{
84 if waywindows.len() == states.len() && waywindows.len() == set_callbacks.len() {
85 let mut internal_recievers: Vec<mpsc::Receiver<InternalHandle>> = Vec::new();
86 states.iter().enumerate().for_each(|(index, state)| {
87 internal_recievers.push(helper_fn_for_deploy(
88 waywindows[index].layer_name.clone(),
89 state,
90 ));
91 });
92
93 loop {
94 states.iter().enumerate().for_each(|(index, state)| {
95 helper_fn_internal_handle(
96 state,
97 &mut set_callbacks[index],
98 &mut internal_recievers[index],
99 &mut waywindows[index],
100 );
101 });
102 waywindows.iter_mut().for_each(|win| {
103 helper_fn_win_handle(win);
104 });
105
106 let _: Vec<_> = waywindows
107 .iter_mut()
108 .map(|waywindow| {
109 run_loop_once(waywindow);
110 })
111 .collect();
112 }
113 } else {
114 panic!(
115 "The lengths of given vectors are not equal. \n Make sure that given vector lengths are equal"
116 );
117 }
118}
119
120pub fn cast_spell<F>(
121 mut waywindow: SpellWin,
122 state: Option<Arc<RwLock<Box<dyn ForeignController>>>>,
125 mut set_callback: Option<F>,
126) -> Result<(), Box<dyn Error>>
127where
128 F: FnMut(Arc<RwLock<Box<dyn ForeignController>>>),
129{
130 let mut rx = helper_fn_for_deploy(waywindow.layer_name.clone(), &state);
131 loop {
132 helper_fn_internal_handle(&state, &mut set_callback, &mut rx, &mut waywindow);
133 helper_fn_win_handle(&mut waywindow);
134 run_loop_once(&mut waywindow);
135 }
136}
137
138fn helper_fn_internal_handle<F>(
139 state: &Option<Arc<RwLock<Box<dyn ForeignController>>>>,
140 set_callback: &mut Option<F>,
141 rx: &mut mpsc::Receiver<InternalHandle>,
142 waywindow: &mut SpellWin,
143) where
144 F: FnMut(Arc<RwLock<Box<dyn ForeignController>>>),
145{
146 if let Some(callback) = set_callback
147 && state.is_some()
148 && let Ok(int_handle) = rx.try_recv()
149 {
150 match int_handle {
151 InternalHandle::StateValChange((key, data_type)) => {
152 println!("Inside statechange");
153 {
155 let mut state_inst = state.as_ref().unwrap().write().unwrap();
156 state_inst.change_val(&key, data_type);
157 }
158 callback(state.as_ref().unwrap().clone());
159 }
160 InternalHandle::ShowWinAgain => {
161 waywindow.show_again();
162 }
163 InternalHandle::HideWindow => waywindow.hide(),
164 }
165 };
166}
167
168fn helper_fn_for_deploy(
169 layer_name: String,
170 state: &Option<Arc<RwLock<Box<dyn ForeignController>>>>,
171) -> mpsc::Receiver<InternalHandle> {
172 let (tx, rx) = mpsc::channel::<InternalHandle>(20);
173 if let Some(some_state) = state {
174 let state_clone = some_state.clone();
175 std::thread::spawn(|| {
176 let rt = tokio::runtime::Builder::new_current_thread()
177 .enable_all()
178 .build()
179 .unwrap();
180 if let Err(error) = rt.block_on(async move {
181 println!("deploied zbus serive in thread");
182 deploy_zbus_service(state_clone, tx, layer_name).await?;
183 Ok::<_, BusError>(())
184 }) {
185 println!("Dbus Thread panicked witth the following error. \n {error}");
186 panic!("All code panicked");
187 }
188 });
189 }
190 rx
191}
192
193fn helper_fn_win_handle(waywindow: &mut SpellWin) {
194 if let Some(window_handle) = &waywindow.handler
195 && let Ok(handle) = window_handle.try_recv()
196 {
197 match handle {
198 Handle::HideWindow => waywindow.hide(),
199 Handle::ShowWinAgain => waywindow.show_again(),
200 Handle::ToggleWindow => waywindow.toggle(),
201 Handle::GrabKeyboardFocus => waywindow.grab_focus(),
202 Handle::RemoveKeyboardFocus => waywindow.remove_focus(),
203 Handle::AddInputRegion(x, y, width, height) => {
204 waywindow.add_input_region(x, y, width, height);
205 }
206 Handle::SubtractInputRegion(x, y, width, height) => {
207 waywindow.subtract_input_region(x, y, width, height);
208 }
209 Handle::AddOpaqueRegion(x, y, width, height) => {
210 waywindow.add_opaque_region(x, y, width, height);
211 }
212 Handle::SubtractOpaqueRegion(x, y, width, height) => {
213 waywindow.subtract_opaque_region(x, y, width, height);
214 }
215 }
216 }
217}
218
219fn run_loop_once(waywindow: &mut SpellWin) {
220 let is_first_config = waywindow.first_configure;
221 let queue = waywindow.queue.clone();
222 if is_first_config {
223 if let Err(err_value) = queue.borrow_mut().roundtrip(waywindow) {
225 report_error(err_value);
226 }
227 } else {
229 if let Err(err_val) = queue.borrow_mut().blocking_dispatch(waywindow) {
230 panic!("{}", err_val);
231 }
232 }
238}
239
240fn report_error(error_value: DispatchError) {
241 match error_value {
242 DispatchError::Backend(backend) => match backend {
243 backend::WaylandError::Io(std_error) => panic!("{}", std_error),
244 backend::WaylandError::Protocol(protocol) => {
245 if protocol.code == 2 && protocol.object_id == 6 {
246 panic!("Maybe the width or height zero");
247 }
248 }
249 },
250 DispatchError::BadMessage {
251 sender_id,
252 interface,
253 opcode,
254 } => panic!("BadMessage Error: sender: {sender_id} interface: {interface} opcode {opcode}"),
255 }
256}
257